Driver core patches for 2.6.21
Subsystems (26)
PATCH 1/1 Driver core patches for 2.6.21
Here are some driver core patche for 2.6.21.
They do a wide range of things, see the shortlog below for details.
All of these have been in the -mm tree for quite some time.
Please pull from:
master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6.git/
Patches will be sent as a follow-on to this message to lkml for people to see.
thanks,
greg k-h
Documentation/feature-removal-schedule.txt | 9 - arch/powerpc/kernel/of_platform.c | 3 - drivers/amba/bus.c | 13 +- drivers/base/attribute_container.c | 26 ++-- drivers/base/base.h | 2 +- drivers/base/bus.c | 112 +++++++++-- drivers/base/class.c | 2 +- drivers/base/core.c | 293 ++++++++++++++++++++-------- drivers/base/dd.c | 66 ++++--- drivers/base/dmapool.c | 14 +- drivers/base/driver.c | 20 -- drivers/base/firmware_class.c | 10 +- drivers/base/power/main.c | 3 + drivers/base/power/resume.c | 13 ++- drivers/base/power/shutdown.c | 2 - drivers/base/power/suspend.c | 12 ++ drivers/ide/ide-proc.c | 4 - drivers/ieee1394/nodemgr.c | 22 +-- drivers/input/gameport/gameport.c | 39 ++--- drivers/input/serio/serio.c | 41 ++--- drivers/mmc/mmc_sysfs.c | 27 +-- drivers/net/phy/fixed.c | 6 - drivers/net/phy/phy_device.c | 9 +- drivers/pci/pci-driver.c | 6 +- drivers/pci/pci.c | 58 ++++-- drivers/pnp/card.c | 6 - drivers/s390/cio/device.c | 6 + drivers/s390/crypto/ap_bus.c | 28 ++-- drivers/s390/net/qeth_proc.c | 2 - drivers/scsi/hosts.c | 4 +- drivers/usb/core/devices.c | 2 - drivers/usb/core/devio.c | 13 -- drivers/usb/core/driver.c | 12 +- drivers/usb/core/hub.c | 4 +- drivers/usb/core/message.c | 2 +- drivers/usb/host/ohci-hcd.c | 6 - fs/debugfs/file.c | 42 ++++ fs/namei.c | 72 +++++-- fs/super.c | 12 -- fs/sysfs/bin.c | 2 +- fs/sysfs/file.c | 14 +- fs/sysfs/group.c | 6 +- include/linux/debugfs.h | 9 + include/linux/device.h | 69 +++++--- include/linux/kobject.h | 12 +- include/linux/namei.h | 1 + include/linux/pci.h | 2 - include/linux/pm.h | 37 ++++ include/linux/sysfs.h | 4 +- kernel/module.c | 4 +- kernel/power/main.c | 18 ++- lib/kobject.c | 62 +++++- lib/kobject_uevent.c | 26 ++-- lib/kref.c | 2 + net/core/net-sysfs.c | 27 ++- sound/aoa/soundbus/core.c | 80 +++----- 56 files changed, 854 insertions(+), 544 deletions(-)
---------------
Adrian Bunk (1):
the overdue removal of the mount/umount uevents
Akinobu Mita (1):
mod_sysfs_setup() doesn't return errno when kobject_add_dir() failure occurs
Alan Stern (1):
device_schedule_callback() needs a module reference
Andrew Morton (2):
powerpc: make it compile for multithread change
sysfs: bin.c printk fix
Cornelia Huck (7):
driver core: per-subsystem multithreaded probing driver core: don't fail attaching the device if it cannot be bound Driver core: suppress uevents via filter
Driver core: switch firmware_class to uevent_suppress.
kobject: kobject_add() reference leak
qeth: Remove usage of subsys.rwsem
s390: cio: Delay uevents for subchannels
Dan Williams (1):
dev_dbg: check dev_dbg() arguments
David Brownell (1):
define platform wakeup hook, use in pci_enable_wake()
Dmitriy Monakhov (2):
driver core: fix device_add error path
kobject: kobject_shadow_add cleanup
Dmitry Torokhov (4):
driver core: Use attribute groups in struct device_type Driver core: add suspend() and resume() to struct device_type
Input: serio - do not touch bus's rwsem
Input: gameport - do not touch bus's rwsem
Eric Rannaud (1):
uevent: use add_uevent_var() instead of open coding it
Eric W. Biederman (1):
kobject: Comment and warning fixes to kobject.c
Greg Kroah-Hartman (10):
Driver core: remove unneeded completion from driver release path Driver core: remove use of rwsem
SCSI: use the proper semaphore to protect the class lists
USB: remove use of the bus rwsem, as it doesn't really protect anything.
PNP: stop using the subsystem rwsem
IDE: remove rwsem use from ide-proc core
IEEE1394: remove rwsem use from ieee1394 core
PHY: remove rwsem use from phy core
kobject core: remove rwsem from struct subsystem
driver core: bus_add_driver should return an error if no bus
James Morris (1):
security: prevent permission checking of file removal via sysfs_remove_group()
Jean Delvare (1):
dev_printk and new-style class devices
Jean Tourrilhes (1):
Driver core: notify userspace of network device renames
Johannes Berg (1):
s2ram: add arch irq disable/enable hooks
John Anthony Kazos Jr (1):
Kobject: kobject_uevent.c: Collapse unnecessary loop nesting (top_kobj)
Kay Sievers (5):
driver core: fix namespace issue with devices assigned to classes Driver core: udev triggered device-<>driver binding
Driver core: add name to device_type
Driver core: make uevent-environment available in uevent-file Driver core: warn when userspace writes to the uevent file in a non-supported way
Matthias Kaehlcke (2):
Driver core: use mutex instead of semaphore in DMA pool handler drivers/base/attribute_container.c: use mutex instead of binary semaphore
Michael Ellerman (1):
debugfs: Add debugfs_create_u64()
Oliver Neukum (1):
kref: fix CPU ordering with respect to krefs
PATCH 1/46 driver core: fix device_add error path
From: Dmitriy Monakhov <[email protected]>
- At the moment we jump here device was't added to dev->class->devices list yet.
--- drivers/base/core.c | 9 --------- 1 files changed, 0 insertions(+), 9 deletions(-)
drivers/base/core.c +0 -9
@@ -677,15 +677,6 @@ int device_add(struct device *dev)#endif sysfs_remove_link (&dev->kobj,"device" ); } - -down (&dev->class->sem); -/* notify any interfaces that the device is now gone */ -list_for_each_entry (class_intf, &dev->class->interfaces, node) -if (class_intf->remove_dev) - class_intf->remove_dev (dev, class_intf); -/* remove the device from the class list */ -list_del_init (&dev->node); -up (&dev->class->sem); } ueventattrError:device_remove_file (dev, &dev->uevent_attr);
Signature · 1 line
1.5.1.2
PATCH 2/46 driver core: fix namespace issue with devices assigned to classes
From: Kay Sievers <[email protected]>
- uses a kset in "struct class" to keep track of all directories belonging to this class
- merges with the /sys/devices/virtual logic.
- removes the namespace-dir if the last member of that class leaves the directory.
There may be locking or refcounting fixes left, I stopped when it seemed to work with network and sound modules. :)
From: Kay Sievers <[email protected]>
--- drivers/base/class.c | 2 +- drivers/base/core.c | 82 +++++++++++++++++++++++++++++++++++++---------- include/linux/device.h | 3 +- include/linux/kobject.h | 2 + lib/kobject.c | 12 ++++++- lib/kobject_uevent.c | 16 ++++++--- 6 files changed, 89 insertions(+), 28 deletions(-)
drivers/base/class.c +1 -1
@@ -145,6 +145,7 @@ int class_register(struct class * cls)INIT_LIST_HEAD (&cls->children);INIT_LIST_HEAD (&cls->devices);INIT_LIST_HEAD (&cls->interfaces); +kset_init (&cls->class_dirs);init_MUTEX (&cls->sem); error =kobject_set_name (&cls->subsys.kset.kobj,"%s" , cls->name);if (error)
@@ -163,7 +164,6 @@ int class_register(struct class * cls)void class_unregister (struct class * cls) {pr_debug ("device class '%s': unregistering\n" , cls->name); -kobject_unregister (cls->virtual_dir);remove_class_attrs (cls);subsystem_unregister (&cls->subsys); }
drivers/base/core.c +65 -17
112 lines not on this page · raw message
include/linux/device.h +1 -2
@@ -181,10 +181,9 @@ struct class {struct list_head children;struct list_head devices;struct list_head interfaces; +struct kset class_dirs;struct semaphore sem;/* locks both the children and interfaces lists */ -struct kobject *virtual_dir; -struct class_attribute * class_attrs;struct class_device_attribute * class_dev_attrs;struct device_attribute * dev_attrs;
include/linux/kobject.h +2 -0
@@ -89,6 +89,8 @@ extern void kobject_unregister(struct kobject *);extern struct kobject *kobject_get (struct kobject *);extern void kobject_put (struct kobject *); +extern struct kobject *kobject_kset_add_dir (struct kset *kset, +struct kobject *,const char *);extern struct kobject *kobject_add_dir (struct kobject *,const char *);extern char *kobject_get_path (struct kobject *,gfp_t );
lib/kobject.c +10 -2
@@ -488,13 +488,15 @@ static struct kobj_type dir_ktype = { };/** -* kobject_add_dir - add sub directory of object. +* kobject__kset_add_dir - add sub directory of object. +* @kset: kset the directory is belongs to. * @parent: object in which a directory is created. * @name: directory name. * * Add a plain directory object as child of given object. */ -struct kobject *kobject_add_dir (struct kobject *parent,const char *name) +struct kobject *kobject_kset_add_dir (struct kset *kset, +struct kobject *parent,const char *name) {struct kobject *k;int ret;
@@ -506,6 +508,7 @@ struct kobject *kobject_add_dir(struct kobject *parent, const char *name)if (!k)return NULL ; + k->kset = kset; k->parent = parent; k->ktype = &dir_ktype;kobject_set_name (k, name);
@@ -520,6 +523,11 @@ struct kobject *kobject_add_dir(struct kobject *parent, const char *name)return k; } +struct kobject *kobject_add_dir (struct kobject *parent,const char *name) +{ +return kobject_kset_add_dir (NULL , parent, name); +} +/** * kset_init - initialize a kset for use * @k: kset
lib/kobject_uevent.c +10 -6
@@ -115,6 +115,16 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,return 0 ; } +/* originating subsystem */ +if (uevent_ops && uevent_ops->name) + subsystem = uevent_ops->name (kset, kobj); +else + subsystem =kobject_name (&kset->kobj); +if (!subsystem) { +pr_debug ("unset subsytem caused the event to drop!\n" ); +return 0 ; + } +/* environment index */ envp =kzalloc (NUM_ENVP *sizeof (char *),GFP_KERNEL );if (!envp)
@@ -134,12 +144,6 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, goto exit; } -/* originating subsystem */ -if (uevent_ops && uevent_ops->name) - subsystem = uevent_ops->name (kset, kobj); -else - subsystem =kobject_name (&kset->kobj); -/* event environemnt for helper process only */ envp[i++] ="HOME=/" ; envp[i++] ="PATH=/sbin:/bin:/usr/sbin:/usr/bin" ;
Signature · 1 line
1.5.1.2
PATCH 3/46 dev_printk and new-style class devices
From: Jean Delvare <[email protected]>
As the new-style class devices (as opposed to old-style struct class_device) are becoming more widely used, I noticed that the dev_printk-based functions are not working properly with these. New-style class devices have no driver nor bus, almost by definition, and as a result dev_driver_string(), which is used as the first parameter of dev_printk, resolves to an empty string. This causes entries like the following to show in my logs:
i2c-2: adapter [SMBus stub driver] registered
Notice the unaesthetical leading whitespace. In order to fix this problem, I suggest that we extend dev_driver_string to deal with new-style class devices:
--- drivers/base/core.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/base/core.c +2 -1
@@ -43,7 +43,8 @@ int (*platform_notify_remove)(struct device * dev) = NULL;const char *dev_driver_string (struct device *dev) {return dev->driver ? dev->driver->name : - (dev->bus ? dev->bus->name :"" ); + (dev->bus ? dev->bus->name : + (dev->class ? dev->class->name :"" )); }EXPORT_SYMBOL (dev_driver_string);
Signature · 1 line
1.5.1.2
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 5/46 driver core: Use attribute groups in struct device_type
From: Dmitry Torokhov <[email protected]>
Driver core: use attribute groups in struct device_type
Attribute groups are more flexible than attribute lists (an attribute list can be represented by anonymous group) so switch struct device_type to use them.
Also rework attribute creation for devices so that they all cleaned up properly in case of errors.
--- drivers/base/core.c | 115 +++++++++++++++++++++++++++++------------------- include/linux/device.h | 2 +- 2 files changed, 70 insertions(+), 47 deletions(-)
drivers/base/core.c +69 -46
@@ -246,64 +246,95 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,return count; } -static int device_add_groups (struct device *dev) +static int device_add_attributes (struct device *dev, +struct device_attribute *attrs) +{ +int error =0 ; +int i; + +if (attrs) { +for (i =0 ;attr_name (attrs[i]); i++) { + error =device_create_file (dev, &attrs[i]); +if (error) +break ; + } +if (error) +while (--i >=0 ) +device_remove_file (dev, &attrs[i]); + } +return error; +} + +static void device_remove_attributes (struct device *dev, +struct device_attribute *attrs) {int i; + +if (attrs) +for (i =0 ;attr_name (attrs[i]); i++) +device_remove_file (dev, &attrs[i]); +} + +static int device_add_groups (struct device *dev, +struct attribute_group **groups) +{int error =0 ; +int i; -if (dev->groups) { -for (i =0 ; dev->groups[i]; i++) { - error =sysfs_create_group (&dev->kobj, dev->groups[i]); +if (groups) { +for (i =0 ; groups[i]; i++) { + error =sysfs_create_group (&dev->kobj, groups[i]);if (error) {while (--i >=0 ) -sysfs_remove_group (&dev->kobj, dev->groups[i]); - goto out; +sysfs_remove_group (&dev->kobj, groups[i]); +break ; } } } -out:return error; } -static void device_remove_groups (struct device *dev) +static void device_remove_groups (struct device *dev, +struct attribute_group **groups) {int i; -if (dev->groups) { -for (i =0 ; dev->groups[i]; i++) { -sysfs_remove_group (&dev->kobj, dev->groups[i]); - } - } + +if (groups) +for (i =0 ; groups[i]; i++) +sysfs_remove_group (&dev->kobj, groups[i]); }static int device_add_attrs (struct device *dev) {struct class *class = dev->class;struct device_type *type = dev->type; -int error =0 ; -int i; +int error; -if (class && class->dev_attrs) { -for (i =0 ;attr_name (class->dev_attrs[i]); i++) { - error =device_create_file (dev, &class->dev_attrs[i]); -if (error) -break ; - } +if (class) { + error =device_add_attributes (dev, class->dev_attrs);if (error) -while (--i >=0 ) -device_remove_file (dev, &class->dev_attrs[i]); +return error; } -if (type && type->attrs) { -for (i =0 ;attr_name (type->attrs[i]); i++) { - error =device_create_file (dev, &type->attrs[i]); -if (error) -break ; - } +if (type) { + error =device_add_groups (dev, type->groups);if (error) -while (--i >=0 ) -device_remove_file (dev, &type->attrs[i]); + goto err_remove_class_attrs; } + error =device_add_groups (dev, dev->groups); +if (error) + goto err_remove_type_groups; + +return 0 ; + + err_remove_type_groups: +if (type) +device_remove_groups (dev, type->groups); + err_remove_class_attrs: +if (class) +device_remove_attributes (dev, class->dev_attrs); +return error; }
@@ -311,17 +342,14 @@ static void device_remove_attrs(struct device *dev) {struct class *class = dev->class;struct device_type *type = dev->type; -int i; -if (class && class->dev_attrs) { -for (i =0 ;attr_name (class->dev_attrs[i]); i++) -device_remove_file (dev, &class->dev_attrs[i]); - } +device_remove_groups (dev, dev->groups); -if (type && type->attrs) { -for (i =0 ;attr_name (type->attrs[i]); i++) -device_remove_file (dev, &type->attrs[i]); - } +if (type) +device_remove_groups (dev, type->groups); + +if (class) +device_remove_attributes (dev, class->dev_attrs); }
@@ -638,8 +666,6 @@ int device_add(struct device *dev)if ((error =device_add_attrs (dev))) goto AttrsError; -if ((error =device_add_groups (dev))) - goto GroupError;if ((error =device_pm_add (dev))) goto PMError;if ((error =bus_add_device (dev)))
@@ -663,7 +689,7 @@ int device_add(struct device *dev)up (&dev->class->sem); } Done: -kfree (class_name); +kfree (class_name);put_device (dev);return error; AttachError:
@@ -674,8 +700,6 @@ int device_add(struct device *dev)if (dev->bus)blocking_notifier_call_chain (&dev->bus->bus_notifier,BUS_NOTIFY_DEL_DEVICE , dev); -device_remove_groups (dev); - GroupError:device_remove_attrs (dev); AttrsError:if (dev->devt_attr) {
@@ -838,7 +862,6 @@ void device_del(struct device * dev) } }device_remove_file (dev, &dev->uevent_attr); -device_remove_groups (dev);device_remove_attrs (dev);bus_remove_device (dev);
include/linux/device.h +1 -1
@@ -332,7 +332,7 @@ extern struct class_device *class_device_create(struct class *cls,extern void class_device_destroy (struct class *cls,dev_t devt);struct device_type { -struct device_attribute *attrs; +struct attribute_group **groups;int (*uevent)(struct device *dev,char **envp,int num_envp,char *buffer,int buffer_size);void (*release)(struct device *dev);
Signature · 1 line
1.5.1.2
PATCH 6/46 Driver core: add name to device_type
From: Kay Sievers <[email protected]>
If "name" of a device_type is specified, the uevent will contain the device_type name in the DEVTYPE variable. This helps userspace to distingiush between different types of devices, belonging to the same subsystem.
--- drivers/base/core.c | 5 +++++ include/linux/device.h | 10 ++++++++++ 2 files changed, 15 insertions(+), 0 deletions(-)
drivers/base/core.c +5 -0
@@ -157,6 +157,11 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, "MINOR=%u", MINOR(dev->devt)); } +if (dev->type && dev->type->name) +add_uevent_var (envp, num_envp, &i, + buffer, buffer_size, &length, +"DEVTYPE=%s" , dev->type->name); +if (dev->driver) add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
include/linux/device.h +10 -0
@@ -331,7 +331,17 @@ extern struct class_device *class_device_create(struct class *cls, __attribute__((format(printf,5,6)));extern void class_device_destroy (struct class *cls,dev_t devt); +/* +* The type of device, "struct device" is embedded in. A class +* or bus can contain devices of different types +* like "partitions" and "disks", "mouse" and "event". +* This identifies the device type and carries type-specific +* information, equivalent to the kobj_type of a kobject. +* If "name" is specified, the uevent will contain it in +* the DEVTYPE variable. +*/ struct device_type { +const char *name;struct attribute_group **groups;int (*uevent)(struct device *dev,char **envp,int num_envp,char *buffer,int buffer_size);
Signature · 1 line
1.5.1.2
PATCH 7/46 kobject: kobject_shadow_add cleanup
From: Dmitriy Monakhov <[email protected]>
- correct function name in comments
- parrent assignment does metter only inside "if" block, so move it inside this block.
--- lib/kobject.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
lib/kobject.c +2 -2
@@ -157,7 +157,7 @@ static void unlink(struct kobject * kobj) }/** -* kobject_add - add an object to the hierarchy. +* kobject_shadow_add - add an object to the hierarchy. * @kobj: object. * @shadow_parent: sysfs directory to add to. */
@@ -190,8 +190,8 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)list_add_tail (&kobj->entry,&kobj->kset->list);spin_unlock (&kobj->kset->list_lock); + kobj->parent = parent; } - kobj->parent = parent; error =create_dir (kobj, shadow_parent);if (error) {
Signature · 1 line
1.5.1.2
PATCH 8/46 driver core: per-subsystem multithreaded probing
From: Cornelia Huck <[email protected]>
Make multithreaded probing work per subsystem instead of per driver.
It doesn't make much sense to probe the same device for multiple drivers in parallel (after all, only one driver can bind to the device). Instead, create a probing thread for each device that probes the drivers one after another. Also make the decision to use multi-threaded probe per bus instead of per device and adapt the pci code.
--- drivers/base/dd.c | 62 +++++++++++++++++++++++----------------------- drivers/pci/pci-driver.c | 6 +--- include/linux/device.h | 3 +- include/linux/pci.h | 2 - 4 files changed, 33 insertions(+), 40 deletions(-)
drivers/base/dd.c +31 -31
@@ -94,19 +94,11 @@ int device_bind_driver(struct device *dev)return ret; } -struct stupid_thread_structure { -struct device_driver *drv; -struct device *dev; -}; -static atomic_t probe_count =ATOMIC_INIT (0 );static DECLARE_WAIT_QUEUE_HEAD (probe_waitqueue); -static int really_probe (void *void_data) +static int really_probe (struct device *dev,struct device_driver *drv) { -struct stupid_thread_structure *data = void_data; -struct device_driver *drv = data->drv; -struct device *dev = data->dev;int ret =0 ;atomic_inc (&probe_count);
@@ -154,7 +146,6 @@ probe_failed:*/ ret =0 ; done: -kfree (data);atomic_dec (&probe_count);wake_up (&probe_waitqueue);return ret;
@@ -186,16 +177,14 @@ int driver_probe_done(void)* format of the ID structures, nor what is to be considered a match and * what is not. * -* This function returns 1 if a match is found, an error if one occurs -* (that is not -ENODEV or -ENXIO), and 0 otherwise. +* This function returns 1 if a match is found, -ENODEV if the device is +* not registered, and 0 otherwise. * * This function must be called with @dev->sem held. When called for a * USB interface, @dev->parent->sem must be held as well. */ int driver_probe_device (struct device_driver * drv,struct device * dev) { -struct stupid_thread_structure *data; -struct task_struct *probe_task;int ret =0 ;if (!device_is_registered (dev))
@@ -206,19 +195,7 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)pr_debug ("%s: Matched Device %s with Driver %s\n" , drv->bus->name, dev->bus_id, drv->name); - data =kmalloc (sizeof (*data),GFP_KERNEL ); -if (!data) -return -ENOMEM ; - data->drv = drv; - data->dev = dev; - -if (drv->multithread_probe) { - probe_task =kthread_run (really_probe, data, -"probe-%s" , dev->bus_id); -if (IS_ERR (probe_task)) - ret =really_probe (data); - }else - ret =really_probe (data); + ret =really_probe (dev, drv); done:return ret;
@@ -230,30 +207,53 @@ static int __device_attach(struct device_driver * drv, void * data)return driver_probe_device (drv, dev); } +static int device_probe_drivers (void *data) +{ +struct device *dev = data; +int ret =0 ; + +if (dev->bus) { +down (&dev->sem); + ret =bus_for_each_drv (dev->bus,NULL , dev, __device_attach); +up (&dev->sem); + } +return ret; +} +/** * device_attach - try to attach device to a driver. * @dev: device. * * Walk the list of drivers that the bus has and call * driver_probe_device() for each pair. If a compatible -* pair is found, break out and return. +* pair is found, break out and return. If the bus specifies +* multithreaded probing, walking the list of drivers is done +* on a probing thread. * * Returns 1 if the device was bound to a driver; -* 0 if no matching device was found; error code otherwise. +* 0 if no matching device was found or multithreaded probing is done; +* error code otherwise. * * When called for a USB interface, @dev->parent->sem must be held. */ int device_attach (struct device * dev) {int ret =0 ; +struct task_struct *probe_task =ERR_PTR (-ENOMEM );down (&dev->sem);if (dev->driver) { ret =device_bind_driver (dev);if (ret ==0 ) ret =1 ; - }else - ret =bus_for_each_drv (dev->bus,NULL , dev, __device_attach); + }else { +if (dev->bus->multithread_probe) + probe_task =kthread_run (device_probe_drivers, dev, +"probe-%s" , dev->bus_id); +if (IS_ERR (probe_task)) + ret =bus_for_each_drv (dev->bus,NULL , dev, + __device_attach); + }up (&dev->sem);return ret; }
drivers/pci/pci-driver.c +1 -5
@@ -434,11 +434,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, drv->driver.mod_name = mod_name; drv->driver.kobj.ktype = &pci_driver_kobj_type; -if (pci_multithread_probe) - drv->driver.multithread_probe = pci_multithread_probe; -else - drv->driver.multithread_probe = drv->multithread_probe; -spin_lock_init (&drv->dynids.lock);INIT_LIST_HEAD (&drv->dynids.list);
@@ -574,6 +569,7 @@ struct bus_type pci_bus_type = {static int __init pci_driver_init (void ) { + pci_bus_type.multithread_probe = pci_multithread_probe;return bus_register (&pci_bus_type); }
include/linux/device.h +1 -2
@@ -80,6 +80,7 @@ struct bus_type {int (*resume)(struct device * dev); unsigned int drivers_autoprobe:1; + unsigned int multithread_probe:1; };extern int __must_check bus_register (struct bus_type * bus);
@@ -139,8 +140,6 @@ struct device_driver {void (*shutdown) (struct device * dev);int (*suspend) (struct device * dev,pm_message_t state);int (*resume) (struct device * dev); - - unsigned int multithread_probe:1; };
include/linux/pci.h +0 -2
@@ -361,8 +361,6 @@ struct pci_driver {struct pci_error_handlers *err_handler;struct device_driver driver;struct pci_dynids dynids; - -int multithread_probe; };#define to_pci_driver (drv) container_of(drv,struct pci_driver, driver)
Signature · 1 line
1.5.1.2
PATCH 9/46 powerpc: make it compile for multithread change
From: Andrew Morton <[email protected]>
arch/powerpc/kernel/of_platform.c:479: error: unknown field `multithread_probe' specified in initializer
--- arch/powerpc/kernel/of_platform.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-)
arch/powerpc/kernel/of_platform.c +0 -3
@@ -475,9 +475,6 @@ static struct of_platform_driver of_pci_phb_driver = { .name = "of-pci", .match_table = of_pci_phb_ids, .probe = of_pci_phb_probe, - .driver = { - .multithread_probe = 1, - }, };static __init int of_pci_phb_init (void )
Signature · 1 line
1.5.1.2
PATCH 10/46 driver core: don't fail attaching the device if it cannot be bound
From: Cornelia Huck <[email protected]>
Don't fail bus_attach_device() if the device cannot be bound.
If dev->driver has been specified, reset it to NULL if device_bind_driver() failed and add the device as an unbound device. As a result, bus_attach_device() now cannot fail, and we can remove some checking from device_add().
Also remove an unneeded check in bus_rescan_devices_helper().
--- drivers/base/base.h | 2 +- drivers/base/bus.c | 11 ++++------- drivers/base/core.c | 5 +---- drivers/base/dd.c | 6 +++++- 4 files changed, 11 insertions(+), 13 deletions(-)
drivers/base/base.h +1 -1
@@ -16,7 +16,7 @@ extern int cpu_dev_init(void);extern int attribute_container_init (void );extern int bus_add_device (struct device * dev); -extern int bus_attach_device (struct device * dev); +extern void bus_attach_device (struct device * dev);extern void bus_remove_device (struct device * dev);extern struct bus_type *get_bus (struct bus_type * bus);extern void put_bus (struct bus_type * bus);
drivers/base/bus.c +4 -7
@@ -447,7 +447,7 @@ out_put:* - Add device to bus's list of devices. * - Try to attach to driver. */ -int bus_attach_device (struct device * dev) +void bus_attach_device (struct device * dev) {struct bus_type *bus = dev->bus;int ret =0 ;
@@ -456,13 +456,12 @@ int bus_attach_device(struct device * dev) dev->is_registered =1 ;if (bus->drivers_autoprobe) ret =device_attach (dev); -if (ret >=0 ) { +WARN_ON (ret <0 ); +if (ret >=0 )klist_add_tail (&dev->knode_bus, &bus->klist_devices); - ret =0 ; - }else +else dev->is_registered =0 ; } -return ret; }/**
@@ -669,8 +668,6 @@ static int __must_check bus_rescan_devices_helper(struct device *dev, ret =device_attach (dev);if (dev->parent)up (&dev->parent->sem); -if (ret >0 ) - ret =0 ; }return ret <0 ? ret :0 ; }
drivers/base/core.c +1 -4
@@ -677,8 +677,7 @@ int device_add(struct device *dev) goto BusError;if (!dev->uevent_suppress)kobject_uevent (&dev->kobj,KOBJ_ADD ); -if ((error =bus_attach_device (dev))) - goto AttachError; +bus_attach_device (dev);if (parent)klist_add_tail (&dev->knode_parent, &parent->klist_children);
@@ -697,8 +696,6 @@ int device_add(struct device *dev)kfree (class_name);put_device (dev);return error; - AttachError: -bus_remove_device (dev); BusError:device_pm_remove (dev); PMError:
drivers/base/dd.c +5 -1
@@ -232,7 +232,7 @@ static int device_probe_drivers(void *data)* * Returns 1 if the device was bound to a driver; * 0 if no matching device was found or multithreaded probing is done; -* error code otherwise. +* -ENODEV if the device is not registered. * * When called for a USB interface, @dev->parent->sem must be held. */
@@ -246,6 +246,10 @@ int device_attach(struct device * dev) ret =device_bind_driver (dev);if (ret ==0 ) ret =1 ; +else { + dev->driver =NULL ; + ret =0 ; + } }else {if (dev->bus->multithread_probe) probe_task = kthread_run(device_probe_drivers, dev,
Signature · 1 line
1.5.1.2
PATCH 11/46 Driver core: remove unneeded completion from driver release path
The completion in the driver release path is due to ancient history in the _very_ early 2.5 days when we were not tracking the module reference count of attributes. It is not needed at all and can be removed.
Note, we now have an empty release function for the driver structure. This is due to the fact that drivers are statically allocated in the system at this point in time, something which I want to change in the future. But remember, drivers are really code, which is reference counted by the module, unlike devices, which are data and _must_ be reference counted properly in order to work correctly.
--- drivers/base/bus.c | 15 +++++++++++++-- drivers/base/driver.c | 20 -------------------- include/linux/device.h | 1 - 3 files changed, 13 insertions(+), 23 deletions(-)
drivers/base/bus.c +13 -2
@@ -63,8 +63,19 @@ static struct sysfs_ops driver_sysfs_ops = {static void driver_release (struct kobject * kobj) { -struct device_driver * drv =to_driver (kobj); -complete (&drv->unloaded); +/* +* Yes this is an empty release function, it is this way because struct +* device is always a static object, not a dynamic one. Yes, this is +* not nice and bad, but remember, drivers are code, reference counted +* by the module count, not a device, which is really data. And yes, +* in the future I do want to have all drivers be created dynamically, +* and am working toward that goal, but it will take a bit longer... +* +* But do not let this example give _anyone_ the idea that they can +* create a release function without any code in it at all, to do that +* is almost always wrong. If you have any questions about this, +* please send an email to <[email protected]> +*/ }static struct kobj_type ktype_driver = {
drivers/base/driver.c +0 -20
@@ -149,10 +149,6 @@ void put_driver(struct device_driver * drv)* We pass off most of the work to the bus_add_driver() call, * since most of the things we have to do deal with the bus * structures. -* -* 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) {
@@ -162,35 +158,19 @@ int driver_register(struct device_driver * drv)printk (KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n" , drv->name); }klist_init (&drv->klist_devices,NULL ,NULL ); -init_completion (&drv->unloaded);return bus_add_driver (drv); } -/** * driver_unregister - remove driver from system. * @drv: driver. * * Again, we pass off most of the work to the bus-level call. -* -* 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 -* unload until all references are gone. */ void driver_unregister (struct device_driver * drv) {bus_remove_driver (drv); -/* -* If the driver is a module, we are probably in -* the module unload path, and we want to wait -* for everything to unload before we can actually -* finish the unload. -*/ -if (drv->owner) -wait_for_completion (&drv->unloaded); }/**
include/linux/device.h +0 -1
@@ -126,7 +126,6 @@ struct device_driver {const char * name;struct bus_type * bus; -struct completion unloaded;struct kobject kobj;struct klist klist_devices;struct klist_node knode_bus;
Signature · 1 line
1.5.1.2
PATCH 12/46 kref: fix CPU ordering with respect to krefs
From: Oliver Neukum <[email protected]>
some atomic operations are only atomic, not ordered. Thus a CPU is allowed to reorder memory references to an object to before the reference is obtained. This fixes it.
--- lib/kref.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
lib/kref.c +2 -0
@@ -21,6 +21,7 @@void kref_init (struct kref *kref) {atomic_set (&kref->refcount,1 ); +smp_mb (); }/**
@@ -31,6 +32,7 @@ void kref_get(struct kref *kref) {WARN_ON (!atomic_read (&kref->refcount));atomic_inc (&kref->refcount); +smp_mb__after_atomic_inc (); }/**
Signature · 1 line
1.5.1.2
PATCH 13/46 Driver core: notify userspace of network device renames
From: Jean Tourrilhes <[email protected]>
Provide rename event for when we rename network devices.
--- lib/kobject.c | 30 ++++++++++++++++++++++++++++++ net/core/net-sysfs.c | 11 +++++++++++ 2 files changed, 41 insertions(+), 0 deletions(-)
lib/kobject.c +30 -0
@@ -311,13 +311,43 @@ EXPORT_SYMBOL(kobject_set_name);int kobject_rename (struct kobject * kobj,const char *new_name) {int error =0 ; +const char *devpath =NULL ; +char *devpath_string =NULL ; +char *envp[2 ]; kobj =kobject_get (kobj);if (!kobj)return -EINVAL ;if (!kobj->parent)return -EINVAL ; + + devpath =kobject_get_path (kobj,GFP_KERNEL ); +if (!devpath) { + error = -ENOMEM ; + goto out; + } + devpath_string =kmalloc (strlen (devpath) +15 ,GFP_KERNEL ); +if (!devpath_string) { + error = -ENOMEM ; + goto out; + } +sprintf (devpath_string,"DEVPATH_OLD=%s" , devpath); + envp[0 ] = devpath_string; + envp[1 ] =NULL ; +/* Note : if we want to send the new name alone, not the full path, +* we could probably use kobject_name(kobj); */ + error =sysfs_rename_dir (kobj, kobj->parent->dentry, new_name); + +/* This function is mostly/only used for network interface. +* Some hotplug package track interfaces by their name and +* therefore want to know when the name is changed by the user. */ +if (!error) +kobject_uevent_env (kobj,KOBJ_MOVE , envp); + +out: +kfree (devpath_string); +kfree (devpath);kobject_put (kobj);return error;
net/core/net-sysfs.c +11 -0
@@ -424,6 +424,17 @@ static int netdev_uevent(struct device *d, char **envp,if ((size <=0 ) || (i >= num_envp))return -ENOMEM ; +/* pass ifindex to uevent. +* ifindex is useful as it won't change (interface name may change) +* and is what RtNetlink uses natively. */ + envp[i++] = buf; + n =snprintf (buf, size,"IFINDEX=%d" , dev->ifindex) +1 ; + buf += n; + size -= n; + +if ((size <=0 ) || (i >= num_envp)) +return -ENOMEM ; + envp[i] =NULL ;return 0 ; }
Signature · 1 line
1.5.1.2
PATCH 14/46 Driver core: suppress uevents via filter
From: Cornelia Huck <[email protected]>
Suppress uevents for devices if uevent_suppress is set via dev_uevent_filter(). This makes the driver core suppress all device uevents, not just the add event in device_add().
--- drivers/base/core.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
drivers/base/core.c +3 -2
@@ -120,6 +120,8 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)if (ktype == &ktype_device) {struct device *dev =to_dev (kobj); +if (dev->uevent_suppress) +return 0 ;if (dev->bus)return 1 ;if (dev->class)
@@ -675,8 +677,7 @@ int device_add(struct device *dev) goto PMError;if ((error =bus_add_device (dev))) goto BusError; -if (!dev->uevent_suppress) -kobject_uevent (&dev->kobj,KOBJ_ADD ); +kobject_uevent (&dev->kobj,KOBJ_ADD );bus_attach_device (dev);if (parent)klist_add_tail (&dev->knode_parent, &parent->klist_children);
Signature · 1 line
1.5.1.2
PATCH 15/46 Driver core: switch firmware_class to uevent_suppress.
From: Cornelia Huck <[email protected]>
Use uevent_suppress instead of returning an error code in firmware_uevent(). Get rid of the now unneeded FW_STATUS_READY and FW_STATUS_READY_NOHOTPLUG.
--- drivers/base/firmware_class.c | 10 ++-------- 1 files changed, 2 insertions(+), 8 deletions(-)
drivers/base/firmware_class.c +2 -8
@@ -31,8 +31,6 @@ enum {FW_STATUS_LOADING ,FW_STATUS_DONE , FW_STATUS_ABORT, -FW_STATUS_READY , - FW_STATUS_READY_NOHOTPLUG, };static int loading_timeout =60 ;/* In seconds */
@@ -96,9 +94,6 @@ static int firmware_uevent(struct device *dev, char **envp, int num_envp,struct firmware_priv *fw_priv =dev_get_drvdata (dev);int i =0 , len =0 ; -if (!test_bit (FW_STATUS_READY , &fw_priv->status)) -return -ENODEV ; -if (add_uevent_var (envp, num_envp, &i, buffer, buffer_size, &len,"FIRMWARE=%s" , fw_priv->fw_id))return -ENOMEM ;
@@ -333,6 +328,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, f_dev->parent = device; f_dev->class = &firmware_class;dev_set_drvdata (f_dev, fw_priv); + f_dev->uevent_suppress =1 ; retval =device_register (f_dev);if (retval) { printk(KERN_ERR "%s: device_register failed\n",
@@ -382,9 +378,7 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p, }if (uevent) -set_bit (FW_STATUS_READY , &fw_priv->status); -else -set_bit (FW_STATUS_READY_NOHOTPLUG , &fw_priv->status); + f_dev->uevent_suppress =0 ; *dev_p = f_dev; goto out;
Signature · 1 line
1.5.1.2
PATCH 16/46 uevent: use add_uevent_var() instead of open coding it
From: Eric Rannaud <[email protected]>
Make use of add_uevent_var() instead of (often incorrectly) open coding it.
--- drivers/amba/bus.c | 13 +++---- drivers/ieee1394/nodemgr.c | 14 +++---- drivers/mmc/mmc_sysfs.c | 27 ++++++-------- drivers/s390/crypto/ap_bus.c | 28 +++++++-------- net/core/net-sysfs.c | 28 ++++++--------- sound/aoa/soundbus/core.c | 80 +++++++++++++++++------------------------- 6 files changed, 79 insertions(+), 111 deletions(-)
drivers/amba/bus.c +6 -7
@@ -47,14 +47,13 @@ static int amba_match(struct device *dev, struct device_driver *drv)static int amba_uevent (struct device *dev,char **envp,int nr_env,char *buf,int bufsz) {struct amba_device *pcdev =to_amba_device (dev); +int retval =0 , i =0 , len =0 ; -if (nr_env <2 ) -return -ENOMEM ; - -snprintf (buf, bufsz,"AMBA_ID=%08x" , pcdev->periphid); - *envp++ = buf; - *envp++ =NULL ; -return 0 ; + retval =add_uevent_var (envp, nr_env, &i, + buf, bufsz, &len, +"AMBA_ID=%08x" , pcdev->periphid); + envp[i] =NULL ; +return retval; }#else #define amba_uevent NULL
drivers/ieee1394/nodemgr.c +6 -8
@@ -1163,6 +1163,7 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,struct unit_directory *ud;int i =0 ;int length =0 ; +int retval =0 ;/* ieee1394:venNmoNspNverN */ char buf[8 +1 +3 +8 +2 +8 +2 +8 +3 +8 +1 ];
@@ -1176,14 +1177,11 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,#define PUT_ENVP (fmt,val) \ do { \ - int printed; \ - envp[i++] = buffer; \ - printed = snprintf(buffer, buffer_size - length, \ - fmt, val); \ - if ((buffer_size - (length+printed) <= 0) || (i >= num_envp)) \ - return -ENOMEM; \ - length += printed+1; \ - buffer += printed+1; \ + retval = add_uevent_var(envp, num_envp, &i, \ + buffer, buffer_size, &length, \ + fmt, val); \ + if (retval) \ + return retval; \ } while (0)PUT_ENVP ("VENDOR_ID=%06x" , ud->vendor_id);
drivers/mmc/mmc_sysfs.c +11 -16
@@ -86,31 +86,26 @@ mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, {struct mmc_card *card =dev_to_mmc_card (dev);char ccc[13 ]; -int i =0 ; - -#define add_env (fmt,val) \ - ({ \ - int len, ret = -ENOMEM; \ - if (i < num_envp) { \ - envp[i++] = buf; \ - len = snprintf(buf, buf_size, fmt, val) + 1; \ - buf_size -= len; \ - buf += len; \ - if (buf_size >= 0) \ - ret = 0; \ - } \ - ret; \ - }) +int retval =0 , i =0 , length =0 ; + +#define add_env (fmt,val) do { \ + retval = add_uevent_var(envp, num_envp, &i, \ + buf, buf_size, &length, \ + fmt, val); \ + if (retval) \ + return retval; \ +} while (0);for (i =0 ; i <12 ; i++) ccc[i] = card->csd.cmdclass & (1 << i) ?'1' :'0' ; ccc[12 ] ='\0' ; - i =0 ;add_env ("MMC_CCC=%s" , ccc);add_env ("MMC_MANFID=%06x" , card->cid.manfid);add_env ("MMC_NAME=%s" ,mmc_card_name (card));add_env ("MMC_OEMID=%04x" , card->cid.oemid); +#undef add_env + envp[i] =NULL ;return 0 ; }
drivers/s390/crypto/ap_bus.c +13 -15
@@ -423,27 +423,25 @@ static int ap_uevent (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) {struct ap_device *ap_dev =to_ap_dev (dev); -int length; +int retval =0 , length =0 , i =0 ;if (!ap_dev)return -ENODEV ;/* Set up DEV_TYPE environment variable. */ - envp[0 ] = buffer; - length =scnprintf (buffer, buffer_size,"DEV_TYPE=%04X" , - ap_dev->device_type); -if (buffer_size - length <=0 ) -return -ENOMEM ; - buffer += length; - buffer_size -= length; + retval =add_uevent_var (envp, num_envp, &i, + buffer, buffer_size, &length, +"DEV_TYPE=%04X" , ap_dev->device_type); +if (retval) +return retval; +/* Add MODALIAS= */ - envp[1 ] = buffer; - length =scnprintf (buffer, buffer_size,"MODALIAS=ap:t%02X" , - ap_dev->device_type); -if (buffer_size - length <=0 ) -return -ENOMEM ; - envp[2 ] =NULL ; -return 0 ; + retval =add_uevent_var (envp, num_envp, &i, + buffer, buffer_size, &length, +"MODALIAS=ap:t%02X" , ap_dev->device_type); + + envp[i] =NULL ; +return retval; }static struct bus_type ap_bus_type = {
net/core/net-sysfs.c +11 -17
@@ -412,31 +412,25 @@ static int netdev_uevent(struct device *d, char **envp, int num_envp, char *buf, int size) { struct net_device *dev = to_net_dev(d); -int i =0 ; -int n; +int retval, len =0 , i =0 ;/* pass interface to uevent. */ - envp[i++] = buf; - n =snprintf (buf, size,"INTERFACE=%s" , dev->name) +1 ; - buf += n; - size -= n; - -if ((size <=0 ) || (i >= num_envp)) -return -ENOMEM ; + retval =add_uevent_var (envp, num_envp, &i, + buf, size, &len, +"INTERFACE=%s" , dev->name); +if (retval) + goto exit;/* pass ifindex to uevent. * ifindex is useful as it won't change (interface name may change) * and is what RtNetlink uses natively. */ - envp[i++] = buf; - n =snprintf (buf, size,"IFINDEX=%d" , dev->ifindex) +1 ; - buf += n; - size -= n; - -if ((size <=0 ) || (i >= num_envp)) -return -ENOMEM ; + retval =add_uevent_var (envp, num_envp, &i, + buf, size, &len, +"IFINDEX=%d" , dev->ifindex); +exit: envp[i] =NULL ; -return 0 ; +return retval; }#endif
sound/aoa/soundbus/core.c +32 -48
104 lines not on this page · raw message
Signature · 1 line
1.5.1.2
PATCH 17/46 Driver core: add suspend() and resume() to struct device_type
From: Dmitry Torokhov <[email protected]>
Driver core: add suspend() and resume() to struct device_type
In cases when there are devices of different types in the same class we can't use class's implementation of suspend and resume methods and we need to add them to struct device_type instead.
Also fix error handling in resume code (we should not try to call class's resume method iof bus's resume method for the device failed.
--- drivers/base/power/resume.c | 13 ++++++++++++- drivers/base/power/suspend.c | 12 ++++++++++++ include/linux/device.h | 2 ++ 3 files changed, 26 insertions(+), 1 deletions(-)
drivers/base/power/resume.c +12 -1
@@ -26,7 +26,9 @@ int resume_device(struct device * dev)TRACE_DEVICE (dev);TRACE_RESUME (0 ); +down (&dev->sem); +if (dev->power.pm_parent && dev->power.pm_parent->power.power_state.event) { dev_err(dev, "PM: resume from %d, parent %s still %d\n",
@@ -34,15 +36,24 @@ int resume_device(struct device * dev) dev->power.pm_parent->bus_id, dev->power.pm_parent->power.power_state.event); } +if (dev->bus && dev->bus->resume) {dev_dbg (dev,"resuming\n" ); error = dev->bus->resume (dev); } -if (dev->class && dev->class->resume) { + +if (!error && dev->type && dev->type->resume) { +dev_dbg (dev,"resuming\n" ); + error = dev->type->resume (dev); + } + +if (!error && dev->class && dev->class->resume) {dev_dbg (dev,"class resume\n" ); error = dev->class->resume (dev); } +up (&dev->sem); +TRACE_RESUME (error);return error; }
drivers/base/power/suspend.c +12 -0
@@ -78,6 +78,18 @@ int suspend_device(struct device * dev, pm_message_t state)suspend_report_result (dev->class->suspend, error); } +if (!error && dev->type && dev->type->suspend && !dev->power.power_state.event) { +dev_dbg (dev,"%s%s\n" , +suspend_verb (state.event), + ((state.event ==PM_EVENT_SUSPEND ) + &&device_may_wakeup (dev)) + ?", may wakeup" + :"" + ); + error = dev->type->suspend (dev, state); +suspend_report_result (dev->type->suspend, error); + } +if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) { dev_dbg(dev, "%s%s\n", suspend_verb(state.event),
include/linux/device.h +2 -0
@@ -344,6 +344,8 @@ struct device_type {int (*uevent)(struct device *dev,char **envp,int num_envp,char *buffer,int buffer_size);void (*release)(struct device *dev); +int (*suspend)(struct device * dev,pm_message_t state); +int (*resume)(struct device * dev); };/* interface for exporting device attributes */
Signature · 1 line
1.5.1.2
PATCH 18/46 Kobject: kobject_uevent.c: Collapse unnecessary loop nesting (top_kobj)
From: John Anthony Kazos Jr <[email protected]>
Collapses a do..while() loop within an if() to a simple while() loop for simplicity and readability.
--- lib/kobject_uevent.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)
lib/kobject_uevent.c +2 -4
@@ -95,10 +95,8 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,/* search the kset we belong to */ top_kobj = kobj; -if (!top_kobj->kset && top_kobj->parent) { -do { - top_kobj = top_kobj->parent; - }while (!top_kobj->kset && top_kobj->parent); +while (!top_kobj->kset && top_kobj->parent) { + top_kobj = top_kobj->parent; }if (!top_kobj->kset) {pr_debug ("kobject attempted to send uevent without kset!\n" );
Signature · 1 line
1.5.1.2
PATCH 19/46 kobject: kobject_add() reference leak
From: Cornelia Huck <[email protected]>
We leak a reference if we attempt to add a kobject with no name.
--- lib/kobject.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
lib/kobject.c +1 -0
@@ -174,6 +174,7 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)if (!*kobj->k_name) {pr_debug ("kobject attempted to be registered with no name!\n" );WARN_ON (1 ); +kobject_put (kobj);return -EINVAL ; } parent =kobject_get (kobj->parent);
Signature · 1 line
1.5.1.2
PATCH 20/46 Driver core: remove use of rwsem
This lock is never used by the rest of the driver core, so the fact that we are grabbing it here means it isn't correct...
--- drivers/base/power/shutdown.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/base/power/shutdown.c +0 -2
@@ -36,7 +36,6 @@ void device_shutdown(void) {struct device * dev, *devn; -down_write (&devices_subsys.rwsem);list_for_each_entry_safe_reverse (dev, devn, &devices_subsys.kset.list, kobj.entry) {if (dev->bus && dev->bus->shutdown) {
@@ -47,7 +46,6 @@ void device_shutdown(void) dev->driver->shutdown (dev); } } -up_write (&devices_subsys.rwsem);sysdev_shutdown (); }
Signature · 1 line
1.5.1.2
PATCH 21/46 SCSI: use the proper semaphore to protect the class lists
SCSI was using the incorrect lock to protect walking the list of all devices in the class. This patch fixes this.
--- drivers/scsi/hosts.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/hosts.c +2 -2
@@ -435,7 +435,7 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)struct class_device *cdev;struct Scsi_Host *shost =ERR_PTR (-ENXIO ), *p; -down_read (&class->subsys.rwsem); +down (&class->sem);list_for_each_entry (cdev, &class->children, node) { p =class_to_shost (cdev);if (p->host_no == hostnum) {
@@ -443,7 +443,7 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)break ; } } -up_read (&class->subsys.rwsem); +up (&class->sem);return shost; }
Signature · 1 line
1.5.1.2
PATCH 22/46 USB: remove use of the bus rwsem, as it doesn't really protect anything.
The driver core stopped using the rwsem a long time ago, yet the USB core still grabbed the lock, thinking it protected something. This patch removes that useless use.
--- drivers/usb/core/devices.c | 2 -- drivers/usb/core/devio.c | 13 ------------- drivers/usb/core/driver.c | 12 ++++++------ drivers/usb/core/message.c | 2 +- 4 files changed, 7 insertions(+), 22 deletions(-)
drivers/usb/core/devices.c +0 -2
@@ -246,7 +246,6 @@ static char *usb_dump_interface_descriptor(char *start, char *end,if (start > end)return start; -down_read (&usb_bus_type.subsys.rwsem);if (iface) { driver_name = (iface->dev.driver ? iface->dev.driver->name
@@ -263,7 +262,6 @@ static char *usb_dump_interface_descriptor(char *start, char *end, desc->bInterfaceSubClass, desc->bInterfaceProtocol, driver_name); -up_read (&usb_bus_type.subsys.rwsem);return start; }
drivers/usb/core/devio.c +0 -13
@@ -421,14 +421,11 @@ static int claimintf(struct dev_state *ps, unsigned int ifnum)if (test_bit (ifnum, &ps->ifclaimed))return 0 ; -/* lock against other changes to driver bindings */ -down_write (&usb_bus_type.subsys.rwsem); intf =usb_ifnum_to_if (dev, ifnum);if (!intf) err = -ENOENT ;else err =usb_driver_claim_interface (&usbfs_driver, intf, ps); -up_write (&usb_bus_type.subsys.rwsem);if (err ==0 )set_bit (ifnum, &ps->ifclaimed);return err;
@@ -444,8 +441,6 @@ static int releaseintf(struct dev_state *ps, unsigned int ifnum)if (ifnum >=8 *sizeof (ps->ifclaimed))return err; dev = ps->dev; -/* lock against other changes to driver bindings */ -down_write (&usb_bus_type.subsys.rwsem); intf =usb_ifnum_to_if (dev, ifnum);if (!intf) err = -ENOENT ;
@@ -453,7 +448,6 @@ static int releaseintf(struct dev_state *ps, unsigned int ifnum)usb_driver_release_interface (&usbfs_driver, intf); err =0 ; } -up_write (&usb_bus_type.subsys.rwsem);return err; }
@@ -813,7 +807,6 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg)if (copy_from_user (&gd, arg,sizeof (gd)))return -EFAULT ; -down_read (&usb_bus_type.subsys.rwsem); intf =usb_ifnum_to_if (ps->dev, gd.interface);if (!intf || !intf->dev.driver) ret = -ENODATA ;
@@ -822,7 +815,6 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg) sizeof(gd.driver)); ret = (copy_to_user (arg, &gd,sizeof (gd)) ? -EFAULT :0 ); } -up_read (&usb_bus_type.subsys.rwsem);return ret; }
@@ -1351,15 +1343,12 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)/* disconnect kernel driver from interface */ case USBDEVFS_DISCONNECT : - -down_write (&usb_bus_type.subsys.rwsem);if (intf->dev.driver) { driver =to_usb_driver (intf->dev.driver);dev_dbg (&intf->dev,"disconnect by usbfs\n" );usb_driver_release_interface (driver, intf); }else retval = -ENODATA ; -up_write (&usb_bus_type.subsys.rwsem);break ;/* let kernel drivers try to (re)bind to the interface */
@@ -1371,7 +1360,6 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)/* talk directly to the interface's driver */ default : -down_read (&usb_bus_type.subsys.rwsem);if (intf->dev.driver) driver =to_usb_driver (intf->dev.driver);if (driver ==NULL || driver->ioctl ==NULL ) {
@@ -1381,7 +1369,6 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)if (retval == -ENOIOCTLCMD ) retval = -ENOTTY ; } -up_read (&usb_bus_type.subsys.rwsem); }/* cleanup and return */
drivers/usb/core/driver.c +6 -6
@@ -287,9 +287,9 @@ static int usb_unbind_interface(struct device *dev)* way to bind to an interface is to return the private data from * the driver's probe() method. * -* Callers must own the device lock and the driver model's usb_bus_type.subsys -* writelock. So driver probe() entries don't need extra locking, -* but other call contexts may need to explicitly claim those locks. +* Callers must own the device lock, so driver probe() entries don't need +* extra locking, but other call contexts may need to explicitly claim that +* lock. */ int usb_driver_claim_interface (struct usb_driver *driver,struct usb_interface *iface,void * priv)
@@ -330,9 +330,9 @@ EXPORT_SYMBOL(usb_driver_claim_interface);* also causes the driver disconnect() method to be called. * * This call is synchronous, and may not be used in an interrupt context. -* Callers must own the device lock and the driver model's usb_bus_type.subsys -* writelock. So driver disconnect() entries don't need extra locking, -* but other call contexts may need to explicitly claim those locks. +* Callers must own the device lock, so driver disconnect() entries don't +* need extra locking, but other call contexts may need to explicitly claim +* that lock. */ void usb_driver_release_interface (struct usb_driver *driver,struct usb_interface *iface)
drivers/usb/core/message.c +1 -1
@@ -1349,7 +1349,7 @@ static void release_interface(struct device *dev)* * This call is synchronous. The calling context must be able to sleep, * must own the device lock, and must not hold the driver model's USB -* bus rwsem; usb device driver probe() methods cannot use this routine. +* bus mutex; usb device driver probe() methods cannot use this routine. * * Returns zero on success, or else the status code returned by the * underlying call that failed. On successful completion, each interface
Signature · 1 line
1.5.1.2
PATCH 23/46 PNP: stop using the subsystem rwsem
The rwsem is not used to protect anything, so the use of it by the PNP subsystem isn't really useful, and it's doubtful if it really did anything or not. So I've removed it.
--- drivers/pnp/card.c | 6 ------ 1 files changed, 0 insertions(+), 6 deletions(-)
drivers/pnp/card.c +0 -6
@@ -311,7 +311,6 @@ done:return NULL ; found: -down_write (&dev->dev.bus->subsys.rwsem); dev->card_link = clink; dev->dev.driver = &drv->link.driver;if (pnp_bus_type.probe (&dev->dev))
@@ -319,14 +318,11 @@ found:if (device_bind_driver (&dev->dev)) goto err_out; -up_write (&dev->dev.bus->subsys.rwsem); -return dev; err_out: dev->dev.driver =NULL ; dev->card_link =NULL ; -up_write (&dev->dev.bus->subsys.rwsem);return NULL ; }
@@ -340,11 +336,9 @@ void pnp_release_card_device(struct pnp_dev * dev)struct pnp_card_driver * drv = dev->card_link->driver;if (!drv)return ; -down_write (&dev->dev.bus->subsys.rwsem); drv->link.remove = &card_remove;device_release_driver (&dev->dev); drv->link.remove = &card_remove_first; -up_write (&dev->dev.bus->subsys.rwsem); }/*
Signature · 1 line
1.5.1.2
PATCH 24/46 Input: serio - do not touch bus's rwsem
From: Dmitry Torokhov <[email protected]>
The subsystem rwsem is not used by the driver core at all, so there is no point in trying to access it.
--- drivers/input/serio/serio.c | 41 +++++++++++++++-------------------------- 1 files changed, 15 insertions(+), 26 deletions(-)
drivers/input/serio/serio.c +15 -26
@@ -115,18 +115,18 @@ static int serio_match_port(const struct serio_device_id *ids, struct serio *ser* Basic serio -> driver core mappings */ -static void serio_bind_driver (struct serio *serio,struct serio_driver *drv) +static int serio_bind_driver (struct serio *serio,struct serio_driver *drv) {int error; -down_write (&serio_bus.subsys.rwsem); -if (serio_match_port (drv->id_table, serio)) { + serio->dev.driver = &drv->driver;if (serio_connect_driver (serio, drv)) { serio->dev.driver =NULL ; - goto out; +return -ENODEV ; } + error =device_bind_driver (&serio->dev);if (error) { printk(KERN_WARNING
@@ -136,31 +136,21 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) drv->description, error);serio_disconnect_driver (serio); serio->dev.driver =NULL ; - goto out; +return error; } } - out: -up_write (&serio_bus.subsys.rwsem); -} - -static void serio_release_driver (struct serio *serio) -{ -down_write (&serio_bus.subsys.rwsem); -device_release_driver (&serio->dev); -up_write (&serio_bus.subsys.rwsem); +return 0 ; }static void serio_find_driver (struct serio *serio) {int error; -down_write (&serio_bus.subsys.rwsem); error =device_attach (&serio->dev);if (error <0 )printk (KERN_WARNING "serio: device_attach() failed for %s (%s), error: %d\n" , serio->phys, serio->name, error); -up_write (&serio_bus.subsys.rwsem); }
@@ -470,13 +460,12 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * {struct serio *serio =to_serio_port (dev);struct device_driver *drv; -int retval; +int error; - retval =mutex_lock_interruptible (&serio_mutex); -if (retval) -return retval; + error =mutex_lock_interruptible (&serio_mutex); +if (error) +return error; - retval = count;if (!strncmp (buf,"none" , count)) {serio_disconnect_port (serio); }else if (!strncmp (buf,"reconnect" , count)) {
@@ -486,15 +475,15 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *serio_find_driver (serio); }else if ((drv =driver_find (buf, &serio_bus)) !=NULL ) {serio_disconnect_port (serio); -serio_bind_driver (serio,to_serio_driver (drv)); + error =serio_bind_driver (serio,to_serio_driver (drv));put_driver (drv); }else { - retval = -EINVAL ; + error = -EINVAL ; }mutex_unlock (&serio_mutex); -return retval; +return error ? error : count; }static ssize_t serio_show_bind_mode (struct device *dev,struct device_attribute *attr,char *buf)
@@ -665,7 +654,7 @@ static void serio_disconnect_port(struct serio *serio)do { parent = s->parent; -serio_release_driver (s); +device_release_driver (&s->dev);serio_destroy_port (s); }while ((s = parent) != serio); }
@@ -673,7 +662,7 @@ static void serio_disconnect_port(struct serio *serio)/* * Ok, no children left, now disconnect this port */ -serio_release_driver (serio); +device_release_driver (&serio->dev); }void serio_rescan (struct serio *serio)
Signature · 1 line
1.5.1.2
PATCH 25/46 Input: gameport - do not touch bus's rwsem
From: Dmitry Torokhov <[email protected]>
The subsystem rwsem is not used by the driver core at all, so there is no point in trying to access it.
--- drivers/input/gameport/gameport.c | 39 ++++++++++++------------------------ 1 files changed, 13 insertions(+), 26 deletions(-)
drivers/input/gameport/gameport.c +13 -26
@@ -190,16 +190,14 @@ static void gameport_run_poll_handler(unsigned long d)* Basic gameport -> driver core mappings */ -static void gameport_bind_driver (struct gameport *gameport,struct gameport_driver *drv) +static int gameport_bind_driver (struct gameport *gameport,struct gameport_driver *drv) {int error; -down_write (&gameport_bus.subsys.rwsem); - gameport->dev.driver = &drv->driver;if (drv->connect (gameport, drv)) { gameport->dev.driver =NULL ; - goto out; +return -ENODEV ; } error =device_bind_driver (&gameport->dev);
@@ -211,31 +209,21 @@ static void gameport_bind_driver(struct gameport *gameport, struct gameport_driv drv->description, error); drv->disconnect (gameport); gameport->dev.driver =NULL ; - goto out; +return error; } - out: -up_write (&gameport_bus.subsys.rwsem); -} - -static void gameport_release_driver (struct gameport *gameport) -{ -down_write (&gameport_bus.subsys.rwsem); -device_release_driver (&gameport->dev); -up_write (&gameport_bus.subsys.rwsem); +return 0 ; }static void gameport_find_driver (struct gameport *gameport) {int error; -down_write (&gameport_bus.subsys.rwsem); error =device_attach (&gameport->dev);if (error <0 )printk (KERN_WARNING "gameport: device_attach() failed for %s (%s), error: %d\n" , gameport->phys, gameport->name, error); -up_write (&gameport_bus.subsys.rwsem); }
@@ -483,13 +471,12 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut {struct gameport *gameport =to_gameport_port (dev);struct device_driver *drv; -int retval; +int error; - retval =mutex_lock_interruptible (&gameport_mutex); -if (retval) -return retval; + error =mutex_lock_interruptible (&gameport_mutex); +if (error) +return error; - retval = count;if (!strncmp (buf,"none" , count)) {gameport_disconnect_port (gameport); }else if (!strncmp (buf,"reconnect" , count)) {
@@ -499,15 +486,15 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attributgameport_find_driver (gameport); }else if ((drv =driver_find (buf, &gameport_bus)) !=NULL ) {gameport_disconnect_port (gameport); -gameport_bind_driver (gameport,to_gameport_driver (drv)); + error =gameport_bind_driver (gameport,to_gameport_driver (drv));put_driver (drv); }else { - retval = -EINVAL ; + error = -EINVAL ; }mutex_unlock (&gameport_mutex); -return retval; +return error ? error : count; }static struct device_attribute gameport_device_attrs[] = {
@@ -655,7 +642,7 @@ static void gameport_disconnect_port(struct gameport *gameport)do { parent = s->parent; -gameport_release_driver (s); +device_release_driver (&s->dev);gameport_destroy_port (s); }while ((s = parent) != gameport); }
@@ -663,7 +650,7 @@ static void gameport_disconnect_port(struct gameport *gameport)/* * Ok, no children left, now disconnect this port */ -gameport_release_driver (gameport); +device_release_driver (&gameport->dev); }void gameport_rescan (struct gameport *gameport)
Signature · 1 line
1.5.1.2
PATCH 26/46 IDE: remove rwsem use from ide-proc core
The subsystem rwsem is not used by the driver core at all, so the use of it in the ide-proc code of it doesn't make any sense. Perhaps a local lock might be needed, but I do not really think so.
--- drivers/ide/ide-proc.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-)
drivers/ide/ide-proc.c +0 -4
@@ -310,14 +310,12 @@ static int proc_ide_read_driveride_driver_t *ide_drv;int len; -down_read (&dev->bus->subsys.rwsem);if (dev->driver) { ide_drv =container_of (dev->driver, ide_driver_t, gen_driver); len =sprintf (page,"%s version %s\n" , dev->driver->name, ide_drv->version); }else len =sprintf (page,"ide-default version 0.9.newide\n" ); -up_read (&dev->bus->subsys.rwsem);PROC_IDE_READ_RETURN (page,start,off,count,eof,len); }
@@ -327,7 +325,6 @@ static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)int ret =1 ;int err; -down_write (&dev->bus->subsys.rwsem);device_release_driver (dev);/* FIXME: device can still be in use by previous driver */ strlcpy (drive->driver_req, driver,sizeof (drive->driver_req));
@@ -345,7 +342,6 @@ static int ide_replace_subdriver(ide_drive_t *drive, const char *driver) }if (dev->driver && !strcmp (dev->driver->name, driver)) ret =0 ; -up_write (&dev->bus->subsys.rwsem);return ret; }
Signature · 1 line
1.5.1.2
PATCH 27/46 IEEE1394: remove rwsem use from ieee1394 core
The subsystem rwsem is not used by the driver core at all, so the use of it in the ieee1394 code doesn't make any sense. They might possibly want to use a local lock, but as most of these operations are already protected by a local lock, it really doesn't look like it would be needed.
--- drivers/ieee1394/nodemgr.c | 8 -------- 1 files changed, 0 insertions(+), 8 deletions(-)
drivers/ieee1394/nodemgr.c +0 -8
@@ -370,9 +370,7 @@ static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attributeif (state ==1 ) { ud->ignore_driver =1 ; -down_write (&ieee1394_bus_type.subsys.rwsem);device_release_driver (dev); -up_write (&ieee1394_bus_type.subsys.rwsem); }else if (state ==0 ) ud->ignore_driver =0 ;
@@ -1391,12 +1389,10 @@ static void nodemgr_suspend_ne(struct node_entry *ne)if (ud->ne != ne)continue ; -down_write (&ieee1394_bus_type.subsys.rwsem);if (ud->device.driver && (!ud->device.driver->suspend || ud->device.driver->suspend (&ud->device,PMSG_SUSPEND )))device_release_driver (&ud->device); -up_write (&ieee1394_bus_type.subsys.rwsem); }up (&nodemgr_ud_class.sem); }
@@ -1416,10 +1412,8 @@ static void nodemgr_resume_ne(struct node_entry *ne)if (ud->ne != ne)continue ; -down_read (&ieee1394_bus_type.subsys.rwsem);if (ud->device.driver && ud->device.driver->resume) ud->device.driver->resume (&ud->device); -up_read (&ieee1394_bus_type.subsys.rwsem); }up (&nodemgr_ud_class.sem);
@@ -1440,7 +1434,6 @@ static void nodemgr_update_pdrv(struct node_entry *ne)if (ud->ne != ne)continue ; -down_write (&ieee1394_bus_type.subsys.rwsem);if (ud->device.driver) { pdrv = container_of(ud->device.driver, struct hpsb_protocol_driver,
@@ -1448,7 +1441,6 @@ static void nodemgr_update_pdrv(struct node_entry *ne)if (pdrv->update && pdrv->update (ud))device_release_driver (&ud->device); } -up_write (&ieee1394_bus_type.subsys.rwsem); }up (&nodemgr_ud_class.sem); }
Signature · 1 line
1.5.1.2
PATCH 28/46 PHY: remove rwsem use from phy core
The subsystem rwsem is not used by the driver core at all, so the use of it in the phy code doesn't make any sense. They might possibly want to use a local lock, but I am unsure about that.
--- drivers/net/phy/fixed.c | 6 ------ drivers/net/phy/phy_device.c | 9 +-------- 2 files changed, 1 insertions(+), 14 deletions(-)
drivers/net/phy/fixed.c +0 -6
@@ -276,21 +276,15 @@ static int fixed_mdio_register_device(int number, int speed, int duplex)artificially, we are binding the driver here by hand; it will be the same for all the fixed phys anyway. */ -down_write (&phydev->dev.bus->subsys.rwsem); - phydev->dev.driver = &fixed_mdio_driver.driver; err = phydev->dev.driver->probe (&phydev->dev);if (err <0 ) {printk (KERN_ERR "Phy %s: problems with fixed driver\n" ,phydev->dev.bus_id); -up_write (&phydev->dev.bus->subsys.rwsem); goto probe_fail; } err =device_bind_driver (&phydev->dev); - -up_write (&phydev->dev.bus->subsys.rwsem); -if (err) goto probe_fail;
drivers/net/phy/phy_device.c +1 -8
@@ -208,16 +208,12 @@ struct phy_device *phy_attach(struct net_device *dev,* exist, and we should use the genphy driver. */ if (NULL == d->driver) {int err; -down_write (&d->bus->subsys.rwsem); d->driver = &genphy_driver.driver; err = d->driver->probe (d); -if (err >=0 ) err =device_bind_driver (d); -up_write (&d->bus->subsys.rwsem); -if (err)return ERR_PTR (err); }
@@ -258,11 +254,8 @@ void phy_detach(struct phy_device *phydev)* was using the generic driver), we unbind the device * from the generic driver so that there's a chance a * real driver could be loaded */ -if (phydev->dev.driver == &genphy_driver.driver) { -down_write (&phydev->dev.bus->subsys.rwsem); +if (phydev->dev.driver == &genphy_driver.driver)device_release_driver (&phydev->dev); -up_write (&phydev->dev.bus->subsys.rwsem); - } }EXPORT_SYMBOL (phy_detach);
Signature · 1 line
1.5.1.2
PATCH 29/46 qeth: Remove usage of subsys.rwsem
From: Cornelia Huck <[email protected]>
the current driver tree contains the removal of subsys.rwsem. Unfortunately, this breaks qeth. However, it should be no problem to fix the walking of the devices for /proc/qeth:
No need to take subsys.rwsem during walking the devices, driver_find_devices() should already suffice.
--- drivers/s390/net/qeth_proc.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/s390/net/qeth_proc.c +0 -2
@@ -37,7 +37,6 @@ qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)struct device *dev =NULL ;loff_t nr =0 ; -down_read (&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);if (*offset ==0 )return SEQ_START_TOKEN ;while (1 ) {
@@ -53,7 +52,6 @@ qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)static void qeth_procfile_seq_stop (struct seq_file *s,void * it) { -up_read (&qeth_ccwgroup_driver.driver.bus->subsys.rwsem); } static void *
Signature · 1 line
1.5.1.2
PATCH 30/46 kobject core: remove rwsem from struct subsystem
It isn't used at all by the driver core anymore, and the few usages of it within the kernel have now all been fixed as most of them were using it incorrectly. So remove it.
Now the whole struct subsys can be removed from the system, but that's for a later patch...
--- include/linux/kobject.h | 2 -- lib/kobject.c | 4 +--- 2 files changed, 1 insertions(+), 5 deletions(-)
include/linux/kobject.h +0 -2
@@ -22,7 +22,6 @@#include <linux/sysfs.h> #include <linux/compiler.h> #include <linux/spinlock.h> -#include <linux/rwsem.h> #include <linux/kref.h> #include <linux/kernel.h> #include <linux/wait.h>
@@ -177,7 +176,6 @@ extern struct kobject * kset_find_obj(struct kset *, const char *);struct subsystem {struct kset kset; -struct rw_semaphore rwsem; };#define decl_subsys (_name,_type,_uevent_ops) \
lib/kobject.c +1 -3
@@ -652,7 +652,6 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)void subsystem_init (struct subsystem * s) { -init_rwsem (&s->rwsem);kset_init (&s->kset); }
@@ -661,8 +660,7 @@ void subsystem_init(struct subsystem * s)* @s: the subsystem we're registering. * * Once we register the subsystem, we want to make sure that -* the kset points back to this subsystem for correct usage of -* the rwsem. +* the kset points back to this subsystem. */ int subsystem_register (struct subsystem * s)
Signature · 1 line
1.5.1.2
PATCH 31/46 Driver core: make uevent-environment available in uevent-file
From: Kay Sievers <[email protected]>
This allows sysfs to show the environment variables that are available if the uevent happens. This lets userspace not have to cache all of this information as the kernel already knows it.
--- drivers/base/core.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 49 insertions(+), 1 deletions(-)
drivers/base/core.c +49 -1
@@ -246,6 +246,53 @@ static struct kset_uevent_ops device_uevent_ops = { .uevent = dev_uevent, }; +static ssize_t show_uevent (struct device *dev,struct device_attribute *attr, +char *buf) +{ +struct kobject *top_kobj; +struct kset *kset; +char *envp[32 ]; +char data[PAGE_SIZE ]; +char *pos; +int i; +size_t count =0 ; +int retval; + +/* search the kset, the device belongs to */ + top_kobj = &dev->kobj; +if (!top_kobj->kset && top_kobj->parent) { +do { + top_kobj = top_kobj->parent; + }while (!top_kobj->kset && top_kobj->parent); + } +if (!top_kobj->kset) + goto out; + kset = top_kobj->kset; +if (!kset->uevent_ops || !kset->uevent_ops->uevent) + goto out; + +/* respect filter */ +if (kset->uevent_ops && kset->uevent_ops->filter) +if (!kset->uevent_ops->filter (kset, &dev->kobj)) + goto out; + +/* let the kset specific function add its keys */ + pos = data; + retval = kset->uevent_ops->uevent (kset, &dev->kobj, + envp,ARRAY_SIZE (envp), + pos,PAGE_SIZE ); +if (retval) + goto out; + +/* copy keys to file */ +for (i =0 ; envp[i]; i++) { + pos = &buf[count]; + count +=sprintf (pos,"%s\n" , envp[i]); + } +out: +return count; +} +static ssize_t store_uevent (struct device *dev,struct device_attribute *attr,const char *buf,size_t count) {
@@ -621,10 +668,11 @@ int device_add(struct device *dev) BUS_NOTIFY_ADD_DEVICE, dev); dev->uevent_attr.attr.name ="uevent" ; - dev->uevent_attr.attr.mode =S_IWUSR ; + dev->uevent_attr.attr.mode =S_IRUGO |S_IWUSR ;if (dev->driver) dev->uevent_attr.attr.owner = dev->driver->owner; dev->uevent_attr.store = store_uevent; + dev->uevent_attr.show = show_uevent; error =device_create_file (dev, &dev->uevent_attr);if (error) goto attrError;
Signature · 1 line
1.5.1.2
PATCH 32/46 Driver core: warn when userspace writes to the uevent file in a non-supported way
From: Kay Sievers <[email protected]>
In the future we will allow the uevent type to be written to the uevent file to trigger the different types of uevents. But for now, as we only support the ADD event, warn if userspace tries to write anything else to this file.
--- drivers/base/core.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
drivers/base/core.c +3 -0
@@ -296,6 +296,9 @@ out:static ssize_t store_uevent (struct device *dev,struct device_attribute *attr,const char *buf,size_t count) { +if (memcmp (buf,"add" ,3 ) !=0 ) +dev_err (dev,"uevent: unsupported action-string; this will " +"be ignored in a future kernel version" );kobject_uevent (&dev->kobj,KOBJ_ADD );return count; }
Signature · 1 line
1.5.1.2
PATCH 33/46 kobject: Comment and warning fixes to kobject.c
From: Eric W. Biederman <[email protected]>
This dots some i's and crosses some t's after left over from when kobject_kset_add_dir was built from kobject_add_dir.
--- lib/kobject.c | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-)
lib/kobject.c +10 -3
@@ -519,7 +519,7 @@ static struct kobj_type dir_ktype = { };/** -* kobject__kset_add_dir - add sub directory of object. +* kobject_kset_add_dir - add sub directory of object. * @kset: kset the directory is belongs to. * @parent: object in which a directory is created. * @name: directory name.
@@ -545,8 +545,8 @@ struct kobject *kobject_kset_add_dir(struct kset *kset,kobject_set_name (k, name); ret =kobject_register (k);if (ret <0 ) { -printk (KERN_WARNING "kobject_add_dir: " -"kobject_register error: %d\n" , ret); +printk (KERN_WARNING "%s: kobject_register error: %d\n" , + __func__, ret);kobject_del (k);return NULL ; }
@@ -554,6 +554,13 @@ struct kobject *kobject_kset_add_dir(struct kset *kset,return k; } +/** +* kobject_add_dir - add sub directory of object. +* @parent: object in which a directory is created. +* @name: directory name. +* +* Add a plain directory object as child of given object. +*/ struct kobject *kobject_add_dir (struct kobject *parent,const char *name) {return kobject_kset_add_dir (NULL , parent, name);
Signature · 1 line
1.5.1.2
PATCH 34/46 the overdue removal of the mount/umount uevents
From: Adrian Bunk <[email protected]>
This patch contains the overdue removal of the mount/umount uevents.
--- Documentation/feature-removal-schedule.txt | 9 --------- fs/super.c | 12 ------------ include/linux/kobject.h | 8 +++----- lib/kobject_uevent.c | 4 ---- 4 files changed, 3 insertions(+), 30 deletions(-)
Documentation/feature-removal-schedule.txt +0 -9
@@ -134,15 +134,6 @@ Who: Arjan van de Ven <[email protected]> --------------------------- -What: mount/umount uevents -When: February 2007 -Why: These events are not correct, and do not properly let userspace know - when a file system has been mounted or unmounted. Userspace should - poll the /proc/mounts file instead to detect this properly. -Who: Greg Kroah-Hartman <[email protected]> - ---------------------------- - What: USB driver API moves to EXPORT_SYMBOL_GPL When: February 2008 Files: include/linux/usb.h, drivers/usb/core/driver.c
fs/super.c +0 -12
@@ -725,16 +725,6 @@ static int test_bdev_super(struct super_block *s, void *data)return (void *)s->s_bdev == data; } -static void bdev_uevent (struct block_device *bdev,enum kobject_action action) -{ -if (bdev->bd_disk) { -if (bdev->bd_part) -kobject_uevent (&bdev->bd_part->kobj, action); -else -kobject_uevent (&bdev->bd_disk->kobj, action); - } -} - int get_sb_bdev(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, int (*fill_super)(struct super_block *, void *, int),
@@ -782,7 +772,6 @@ int get_sb_bdev(struct file_system_type *fs_type, } s->s_flags |=MS_ACTIVE ; -bdev_uevent (bdev,KOBJ_MOUNT ); }return simple_set_mnt (mnt, s);
@@ -801,7 +790,6 @@ void kill_block_super(struct super_block *sb) {struct block_device *bdev = sb->s_bdev; -bdev_uevent (bdev,KOBJ_UMOUNT );generic_shutdown_super (sb);sync_blockdev (bdev);close_bdev_excl (bdev);
include/linux/kobject.h +3 -5
@@ -42,11 +42,9 @@ enum kobject_action {KOBJ_ADD = (__force kobject_action_t )0x01 ,/* exclusive to core */ KOBJ_REMOVE = (__force kobject_action_t )0x02 ,/* exclusive to core */ KOBJ_CHANGE = (__force kobject_action_t )0x03 ,/* device state change */ -KOBJ_MOUNT = (__force kobject_action_t )0x04 ,/* mount event for block devices (broken) */ -KOBJ_UMOUNT = (__force kobject_action_t )0x05 ,/* umount event for block devices (broken) */ -KOBJ_OFFLINE = (__force kobject_action_t )0x06 ,/* device offline */ -KOBJ_ONLINE = (__force kobject_action_t )0x07 ,/* device online */ - KOBJ_MOVE = (__force kobject_action_t) 0x08, /* device move */ +KOBJ_OFFLINE = (__force kobject_action_t )0x04 ,/* device offline */ +KOBJ_ONLINE = (__force kobject_action_t )0x05 ,/* device online */ + KOBJ_MOVE = (__force kobject_action_t) 0x06, /* device move */ }; struct kobject {
lib/kobject_uevent.c +0 -4
@@ -42,10 +42,6 @@ static char *action_to_string(enum kobject_action action)return "remove" ;case KOBJ_CHANGE :return "change" ; -case KOBJ_MOUNT : -return "mount" ; -case KOBJ_UMOUNT : -return "umount" ;case KOBJ_OFFLINE :return "offline" ;case KOBJ_ONLINE :
Signature · 1 line
1.5.1.2
PATCH 35/46 debugfs: Add debugfs_create_u64()
From: Michael Ellerman <[email protected]>
I went to use this the other day, only to find it didn't exist.
It's a straight copy of the debugfs u32 code, then s/u32/u64/. A quick test shows it seems to be working.
--- fs/debugfs/file.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/linux/debugfs.h | 9 +++++++++ 2 files changed, 51 insertions(+), 0 deletions(-)
fs/debugfs/file.c +42 -0
@@ -179,6 +179,48 @@ struct dentry *debugfs_create_u32(const char *name, mode_t mode, }EXPORT_SYMBOL_GPL (debugfs_create_u32); +static void debugfs_u64_set (void *data,u64 val) +{ + *(u64 *)data = val; +} + +static u64 debugfs_u64_get (void *data) +{ +return *(u64 *)data; +} +DEFINE_SIMPLE_ATTRIBUTE (fops_u64, debugfs_u64_get, debugfs_u64_set,"%llu\n" ); + +/** +* debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value +* @name: a pointer to a string containing the name of the file to create. +* @mode: the permission that the file should have +* @parent: a pointer to the parent dentry for this file. This should be a +* directory dentry if set. If this parameter is %NULL, then the +* file will be created in the root of the debugfs filesystem. +* @value: a pointer to the variable that the file should read to and write +* from. +* +* This function creates a file in debugfs with the given name that +* contains the value of the variable @value. If the @mode variable is so +* set, it can be read from, and written to. +* +* This function will return a pointer to a dentry if it succeeds. This +* pointer must be passed to the debugfs_remove() function when the file is +* to be removed (no automatic cleanup happens if your module is unloaded, +* you are responsible here.) If an error occurs, %NULL will be returned. +* +* If debugfs is not enabled in the kernel, the value -%ENODEV will be +* returned. It is not wise to check for this value, but rather, check for +* %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling +* code. +*/ +struct dentry *debugfs_create_u64 (const char *name,mode_t mode, +struct dentry *parent,u64 *value) +{ +return debugfs_create_file (name, mode, parent, value, &fops_u64); +} +EXPORT_SYMBOL_GPL (debugfs_create_u64); +static ssize_t read_file_bool (struct file *file,char __user *user_buf,size_t count,loff_t *ppos) {
include/linux/debugfs.h +9 -0
@@ -44,6 +44,8 @@ struct dentry *debugfs_create_u16(const char *name, mode_t mode, struct dentry *parent, u16 *value);struct dentry *debugfs_create_u32 (const char *name,mode_t mode,struct dentry *parent,u32 *value); +struct dentry *debugfs_create_u64 (const char *name,mode_t mode, +struct dentry *parent,u64 *value);struct dentry *debugfs_create_bool (const char *name,mode_t mode,struct dentry *parent,u32 *value);
@@ -104,6 +106,13 @@ static inline struct dentry *debugfs_create_u32(const char *name, mode_t mode,return ERR_PTR (-ENODEV ); } +static inline struct dentry *debugfs_create_u64 (const char *name,mode_t mode, +struct dentry *parent, +u64 *value) +{ +return ERR_PTR (-ENODEV ); +} +static inline struct dentry *debugfs_create_bool (const char *name,mode_t mode,struct dentry *parent,u32 *value)
Signature · 1 line
1.5.1.2
PATCH 36/46 driver core: bus_add_driver should return an error if no bus
As pointed out by Dave Jones.
--- drivers/base/bus.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/base/bus.c +1 -1
@@ -603,7 +603,7 @@ int bus_add_driver(struct device_driver *drv)int error =0 ;if (!bus) -return 0 ; +return -EINVAL ;pr_debug ("bus %s: add driver %s\n" , bus->name, drv->name); error =kobject_set_name (&drv->kobj,"%s" , drv->name);
Signature · 1 line
1.5.1.2
PATCH 37/46 Driver core: use mutex instead of semaphore in DMA pool handler
From: Matthias Kaehlcke <[email protected]>
the DMA pool handler uses a semaphore as mutex. use the mutex API instead of the (binary) semaphore
--- drivers/base/dmapool.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-)
drivers/base/dmapool.c +7 -7
@@ -37,7 +37,7 @@ struct dma_page { /* cacheable header for 'allocation' bytes */ #define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000) -static DECLARE_MUTEX (pools_lock); +static DEFINE_MUTEX (pools_lock);static ssize_t show_pools (struct device *dev,struct device_attribute *attr,char *buf)
@@ -55,7 +55,7 @@ show_pools (struct device *dev, struct device_attribute *attr, char *buf) size -= temp; next += temp; -down (&pools_lock); +mutex_lock (&pools_lock);list_for_each_entry (pool, &dev->dma_pools, pools) {unsigned pages =0 ;unsigned blocks =0 ;
@@ -73,7 +73,7 @@ show_pools (struct device *dev, struct device_attribute *attr, char *buf) size -= temp; next += temp; } -up (&pools_lock); +mutex_unlock (&pools_lock);return PAGE_SIZE - size; }
@@ -143,7 +143,7 @@ dma_pool_create (const char *name, struct device *dev,if (dev) {int ret; -down (&pools_lock); +mutex_lock (&pools_lock);if (list_empty (&dev->dma_pools)) ret =device_create_file (dev, &dev_attr_pools);else
@@ -155,7 +155,7 @@ dma_pool_create (const char *name, struct device *dev,kfree (retval); retval =NULL ; } -up (&pools_lock); +mutex_unlock (&pools_lock); }else INIT_LIST_HEAD (&retval->pools);
@@ -231,11 +231,11 @@ pool_free_page (struct dma_pool *pool, struct dma_page *page)void dma_pool_destroy (struct dma_pool *pool) { -down (&pools_lock); +mutex_lock (&pools_lock);list_del (&pool->pools);if (pool->dev &&list_empty (&pool->dev->dma_pools))device_remove_file (pool->dev, &dev_attr_pools); -up (&pools_lock); +mutex_unlock (&pools_lock);while (!list_empty (&pool->page_list)) {struct dma_page *page;
Signature · 1 line
1.5.1.2
PATCH 38/46 sysfs: bin.c printk fix
From: Andrew Morton <[email protected]>
fs/sysfs/bin.c: In function 'read':fs/sysfs/bin.c:77: warning: format '%zd' expects type 'signed size_t', but argument 4 has type 'int'
--- fs/sysfs/bin.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
fs/sysfs/bin.c +1 -1
@@ -59,7 +59,7 @@ read(struct file * file, char __user * userbuf, size_t count, loff_t * off)if (copy_to_user (userbuf, buffer, count))return -EFAULT ; -pr_debug ("offs = %lld, *off = %lld, count = %zd\n" , offs, *off, count); +pr_debug ("offs = %lld, *off = %lld, count = %d\n" , offs, *off, count); *off = offs + count;
Signature · 1 line
1.5.1.2
PATCH 39/46 s390: cio: Delay uevents for subchannels
From: Cornelia Huck <[email protected]>
We often have the situation that we register a subchannel and start device recognition, only to find out that the device is not usable after all, which triggers an unregister of the subchannel. This often happens on hundreds of subchannels on a LPAR, leading to a storm of events which aren't of any use. Therefore, use uevent_suppress to delay the KOBJ_ADD uevent for a subchannel until we know that its ccw_device is to be registered.
--- drivers/s390/cio/device.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
drivers/s390/cio/device.c +6 -0
@@ -871,6 +871,12 @@ io_subchannel_register(struct work_struct *work) } goto out; } +/* +* Now we know this subchannel will stay, we can throw +* our delayed uevent. +*/ + sch->dev.uevent_suppress =0 ; +kobject_uevent (&sch->dev.kobj,KOBJ_ADD );/* make it known to the system */ ret =ccw_device_register (cdev);if (ret) {
Signature · 1 line
1.5.1.2
PATCH 40/46 device_schedule_callback() needs a module reference
From: Alan Stern <[email protected]>
This patch (as896b) fixes an oversight in the design of device_schedule_callback(). It is necessary to acquire a reference to the module owning the callback routine, to prevent the module from being unloaded before the callback can run.
--- drivers/base/core.c | 16 ++++++++++------ fs/sysfs/file.c | 14 +++++++++++--- include/linux/device.h | 8 ++++++-- include/linux/sysfs.h | 4 ++-- 4 files changed, 29 insertions(+), 13 deletions(-)
drivers/base/core.c +10 -6
@@ -480,9 +480,10 @@ void device_remove_bin_file(struct device *dev, struct bin_attribute *attr)EXPORT_SYMBOL_GPL (device_remove_bin_file);/** -* device_schedule_callback - helper to schedule a callback for a device +* device_schedule_callback_owner - helper to schedule a callback for a device * @dev: device. * @func: callback function to invoke later. +* @owner: module owning the callback routine * * Attribute methods must not unregister themselves or their parent device * (which would amount to the same thing). Attempts to do so will deadlock,
@@ -493,20 +494,23 @@ EXPORT_SYMBOL_GPL(device_remove_bin_file);* argument in the workqueue's process context. @dev will be pinned until * @func returns. * +* This routine is usually called via the inline device_schedule_callback(), +* which automatically sets @owner to THIS_MODULE. +* * Returns 0 if the request was submitted, -ENOMEM if storage could not -* be allocated. +* be allocated, -ENODEV if a reference to @owner isn't available. * * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an * underlying sysfs routine (since it is intended for use by attribute * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. */ -int device_schedule_callback (struct device *dev, -void (*func)(struct device *)) +int device_schedule_callback_owner (struct device *dev, +void (*func)(struct device *),struct module *owner) {return sysfs_schedule_callback (&dev->kobj, - (void (*)(void *)) func, dev); + (void (*)(void *)) func, dev, owner); } -EXPORT_SYMBOL_GPL (device_schedule_callback); +EXPORT_SYMBOL_GPL (device_schedule_callback_owner);static void klist_children_get (struct klist_node *n) {
fs/sysfs/file.c +11 -3
@@ -633,6 +633,7 @@ struct sysfs_schedule_callback_struct {struct kobject *kobj;void (*func)(void *);void *data; +struct module *owner;struct work_struct work; };
@@ -643,6 +644,7 @@ static void sysfs_schedule_callback_work(struct work_struct *work) (ss->func)(ss->data);kobject_put (ss->kobj); +module_put (ss->owner);kfree (ss); }
@@ -651,6 +653,7 @@ static void sysfs_schedule_callback_work(struct work_struct *work)* @kobj: object we're acting for. * @func: callback function to invoke later. * @data: argument to pass to @func. +* @owner: module owning the callback code * * sysfs attribute methods must not unregister themselves or their parent * kobject (which would amount to the same thing). Attempts to do so will
@@ -663,20 +666,25 @@ static void sysfs_schedule_callback_work(struct work_struct *work)* until @func returns. * * Returns 0 if the request was submitted, -ENOMEM if storage could not -* be allocated. +* be allocated, -ENODEV if a reference to @owner isn't available. */ int sysfs_schedule_callback (struct kobject *kobj,void (*func)(void *), -void *data) +void *data,struct module *owner) {struct sysfs_schedule_callback_struct *ss; +if (!try_module_get (owner)) +return -ENODEV ; ss =kmalloc (sizeof (*ss),GFP_KERNEL ); -if (!ss) +if (!ss) { +module_put (owner);return -ENOMEM ; + }kobject_get (kobj); ss->kobj = kobj; ss->func = func; ss->data = data; + ss->owner = owner;INIT_WORK (&ss->work, sysfs_schedule_callback_work);schedule_work (&ss->work);return 0 ;
include/linux/device.h +6 -2
@@ -367,8 +367,12 @@ extern int __must_check device_create_bin_file(struct device *dev, struct bin_attribute *attr);extern void device_remove_bin_file (struct device *dev,struct bin_attribute *attr); -extern int device_schedule_callback (struct device *dev, -void (*func)(struct device *)); +extern int device_schedule_callback_owner (struct device *dev, +void (*func)(struct device *),struct module *owner); + +/* This is a macro to avoid include problems with THIS_MODULE */ +#define device_schedule_callback (dev, func) \ + device_schedule_callback_owner(dev, func, THIS_MODULE)/* device resource management */ typedef void (*dr_release_t )(struct device *dev,void *res);
include/linux/sysfs.h +2 -2
@@ -80,7 +80,7 @@ struct sysfs_ops {#ifdef CONFIG_SYSFS extern int sysfs_schedule_callback (struct kobject *kobj, -void (*func)(void *),void *data); +void (*func)(void *),void *data,struct module *owner);extern int __must_check sysfs_create_dir (struct kobject *,struct dentry *);
@@ -137,7 +137,7 @@ extern int __must_check sysfs_init(void);#else /* CONFIG_SYSFS */ static inline int sysfs_schedule_callback (struct kobject *kobj, -void (*func)(void *),void *data) +void (*func)(void *),void *data,struct module *owner) {return -ENOSYS ; }
Signature · 1 line
1.5.1.2
PATCH 41/46 security: prevent permission checking of file removal via sysfs_remove_group()
From: James Morris <[email protected]>
Prevent permission checking from being performed when the kernel wants to unconditionally remove a sysfs group, by introducing an kernel-only variant of lookup_one_len(), lookup_one_len_kern().
Additionally, as sysfs_remove_group() does not check the return value of the lookup before using it, a BUG_ON has been added to pinpoint the cause of any problems potentially caused by this (and as a form of annotation).
--- fs/namei.c | 72 +++++++++++++++++++++++++++++++++++------------- fs/sysfs/group.c | 6 +++- include/linux/namei.h | 1 + 3 files changed, 57 insertions(+), 22 deletions(-)
fs/namei.c +52 -20
@@ -1243,22 +1243,13 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,return err; } -/* -* Restricted form of lookup. Doesn't follow links, single-component only, -* needs parent already locked. Doesn't follow mounts. -* SMP-safe. -*/ -static struct dentry *__lookup_hash (struct qstr *name,struct dentry * base,struct nameidata *nd) +static inline struct dentry *__lookup_hash_kern (struct qstr *name,struct dentry *base,struct nameidata *nd) { -struct dentry * dentry; +struct dentry *dentry;struct inode *inode;int err; inode = base->d_inode; - err =permission (inode,MAY_EXEC , nd); - dentry =ERR_PTR (err); -if (err) - goto out;/* * See if the low-level filesystem might want
@@ -1287,35 +1278,76 @@ out:return dentry; } +/* +* Restricted form of lookup. Doesn't follow links, single-component only, +* needs parent already locked. Doesn't follow mounts. +* SMP-safe. +*/ +static inline struct dentry *__lookup_hash (struct qstr *name,struct dentry *base,struct nameidata *nd) +{ +struct dentry *dentry; +struct inode *inode; +int err; + + inode = base->d_inode; + + err =permission (inode,MAY_EXEC , nd); + dentry =ERR_PTR (err); +if (err) + goto out; + + dentry =__lookup_hash_kern (name, base, nd); +out: +return dentry; +} +static struct dentry *lookup_hash (struct nameidata *nd) {return __lookup_hash (&nd->last, nd->dentry, nd); }/* SMP-safe */ -struct dentry *lookup_one_len (const char * name,struct dentry * base,int len) +static inline int __lookup_one_len (const char *name,struct qstr *this,struct dentry *base,int len) {unsigned long hash; -struct qstr this;unsigned int c; - this.name = name; - this.len = len; + this->name = name; + this->len = len;if (!len) - goto access; +return -EACCES ; hash =init_name_hash ();while (len--) { c = *(const unsigned char *)name++;if (c =='/' || c =='\0' ) - goto access; +return -EACCES ; hash =partial_name_hash (c, hash); } - this.hash =end_name_hash (hash); + this->hash =end_name_hash (hash); +return 0 ; +} +struct dentry *lookup_one_len (const char *name,struct dentry *base,int len) +{ +int err; +struct qstr this; + + err =__lookup_one_len (name, &this, base, len); +if (err) +return ERR_PTR (err);return __lookup_hash (&this, base,NULL ); -access: -return ERR_PTR (-EACCES ); +} + +struct dentry *lookup_one_len_kern (const char *name,struct dentry *base,int len) +{ +int err; +struct qstr this; + + err =__lookup_one_len (name, &this, base, len); +if (err) +return ERR_PTR (err); +return __lookup_hash_kern (&this, base,NULL ); }/*
fs/sysfs/group.c +4 -2
@@ -70,9 +70,11 @@ void sysfs_remove_group(struct kobject * kobj, {struct dentry * dir; -if (grp->name) - dir =lookup_one_len (grp->name, kobj->dentry, +if (grp->name) { + dir =lookup_one_len_kern (grp->name, kobj->dentry,strlen (grp->name)); +BUG_ON (IS_ERR (dir)); + }else dir =dget (kobj->dentry);
include/linux/namei.h +1 -0
@@ -82,6 +82,7 @@ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);extern void release_open_intent (struct nameidata *);extern struct dentry *lookup_one_len (const char *,struct dentry *,int ); +extern struct dentry *lookup_one_len_kern (const char *,struct dentry *,int );extern int follow_down (struct vfsmount **,struct dentry **);extern int follow_up (struct vfsmount **,struct dentry **);
Signature · 1 line
1.5.1.2
PATCH 42/46 define platform wakeup hook, use in pci_enable_wake()
From: David Brownell <[email protected]>
This defines a platform hook to enable/disable a device as a wakeup event source. It's initially for use with ACPI, but more generally it could be used whenever enable_irq_wake()/disable_irq_wake() don't suffice.
The hook is called -- if available -- inside pci_enable_wake(); and the semantics of that call are enhanced so that support for PCI PME# is no longer needed. It can now work for devices with "legacy PCI PM", when platform support allows it. (That support would use some board-specific signal for for the same purpose as PME#.)
--- drivers/base/power/main.c | 3 ++ drivers/pci/pci.c | 58 +++++++++++++++++++++++++++++++------------- include/linux/pm.h | 19 ++++++++++++++ 3 files changed, 63 insertions(+), 17 deletions(-)
drivers/base/power/main.c +3 -0
@@ -29,6 +29,9 @@ LIST_HEAD(dpm_off_irq);DECLARE_MUTEX (dpm_sem);DECLARE_MUTEX (dpm_list_sem); +int (*platform_enable_wakeup)(struct device *dev,int is_on); + +/** * device_pm_set_parent - Specify power dependency. * @dev: Device who needs power.
drivers/pci/pci.c +41 -17
93 lines not on this page · raw message
include/linux/pm.h +19 -0
@@ -273,6 +273,20 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);__suspend_report_result (__FUNCTION__, fn, ret); \ } while (0) +/* +* Platform hook to activate device wakeup capability, if that's not already +* handled by enable_irq_wake() etc. +* Returns zero on success, else negative errno +*/ +extern int (*platform_enable_wakeup)(struct device *dev, int is_on); + +static inline int call_platform_enable_wakeup (struct device *dev,int is_on) +{ +if (platform_enable_wakeup) +return (*platform_enable_wakeup)(dev, is_on); +return 0 ; +} +#else /* !CONFIG_PM */ static inline int device_suspend (pm_message_t state)
@@ -294,6 +308,11 @@ static inline void dpm_runtime_resume(struct device * dev)#define suspend_report_result (fn, ret) do { } while (0) +static inline int call_platform_enable_wakeup (struct device *dev,int is_on) +{ +return -EIO ; +} +#endif /* changes to device_may_wakeup take effect on the next pm state change.
Signature · 1 line
1.5.1.2
PATCH 43/46 s2ram: add arch irq disable/enable hooks
From: Johannes Berg <[email protected]>
After some more discussion this patch replaces it:
From: Johannes Berg <[email protected]>
Subject: suspend: add arch irq disable/enable hooks
For powermac, we need to do some things between suspending devices and device_power_off, for example setting the decrementer. This patch allows architectures to define arch_s2ram_{en,dis}able_irqs in their asm/suspend.h to have control over this step.
--- include/linux/pm.h | 18 ++++++++++++++++++ kernel/power/main.c | 18 +++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-)
include/linux/pm.h +18 -0
@@ -166,6 +166,24 @@ extern struct pm_ops *pm_ops;extern int pm_suspend (suspend_state_t state); +/** +* arch_suspend_disable_irqs - disable IRQs for suspend +* +* Disables IRQs (in the default case). This is a weak symbol in the common +* code and thus allows architectures to override it if more needs to be +* done. Not called for suspend to disk. +*/ +extern void arch_suspend_disable_irqs (void ); + +/** +* arch_suspend_enable_irqs - enable IRQs after suspend +* +* Enables IRQs (in the default case). This is a weak symbol in the common +* code and thus allows architectures to override it if more needs to be +* done. Not called for suspend to disk. +*/ +extern void arch_suspend_enable_irqs (void ); +/* * Device power management */
kernel/power/main.c +15 -3
@@ -111,13 +111,24 @@ static int suspend_prepare(suspend_state_t state)return error; } +/* default implementation */ +void __attribute__ ((weak))arch_suspend_disable_irqs (void ) +{ +local_irq_disable (); +} + +/* default implementation */ +void __attribute__ ((weak))arch_suspend_enable_irqs (void ) +{ +local_irq_enable (); +}int suspend_enter (suspend_state_t state) {int error =0 ; -unsigned long flags; -local_irq_save (flags); +arch_suspend_disable_irqs (); +BUG_ON (!irqs_disabled ());if ((error =device_power_down (PMSG_SUSPEND ))) {printk (KERN_ERR "Some devices failed to power down\n" );
@@ -126,7 +137,8 @@ int suspend_enter(suspend_state_t state) error = pm_ops->enter (state);device_power_up (); Done: -local_irq_restore (flags); +arch_suspend_enable_irqs (); +BUG_ON (irqs_disabled ());return error; }
Signature · 1 line
1.5.1.2
PATCH 44/46 mod_sysfs_setup() doesn't return errno when kobject_add_dir() failure occurs
From: Akinobu Mita <[email protected]>
mod_sysfs_setup() doesn't return an errno when kobject_add_dir() for module "holders" directory fails. So caller of mod_sysfs_setup() will keep going and get oops.
--- kernel/module.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
kernel/module.c +3 -1
@@ -1148,8 +1148,10 @@ int mod_sysfs_setup(struct module *mod, goto out; mod->holders_dir =kobject_add_dir (&mod->mkobj.kobj,"holders" ); -if (!mod->holders_dir) +if (!mod->holders_dir) { + err = -ENOMEM ; goto out_unreg; + } err =module_param_sysfs_setup (mod, kparam, num_params);if (err)
Signature · 1 line
1.5.1.2
PATCH 45/46 drivers/base/attribute_container.c: use mutex instead of binary semaphore
From: Matthias Kaehlcke <[email protected]>
use mutex instead of binary semaphore indrivers/base/attribute_container.c
--- drivers/base/attribute_container.c | 26 +++++++++++++------------- 1 files changed, 13 insertions(+), 13 deletions(-)
drivers/base/attribute_container.c +13 -13
@@ -62,7 +62,7 @@ EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);static struct list_head attribute_container_list; -static DECLARE_MUTEX (attribute_container_mutex); +static DEFINE_MUTEX (attribute_container_mutex);/** * attribute_container_register - register an attribute container
@@ -77,9 +77,9 @@ attribute_container_register(struct attribute_container *cont)klist_init (&cont->containers,internal_container_klist_get, internal_container_klist_put); -down (&attribute_container_mutex); +mutex_lock (&attribute_container_mutex);list_add_tail (&cont->node, &attribute_container_list); -up (&attribute_container_mutex); +mutex_unlock (&attribute_container_mutex);return 0 ; }
@@ -94,7 +94,7 @@ int attribute_container_unregister(struct attribute_container *cont) {int retval = -EBUSY ; -down (&attribute_container_mutex); +mutex_lock (&attribute_container_mutex);spin_lock (&cont->containers.k_lock);if (!list_empty (&cont->containers.k_list)) goto out;
@@ -102,7 +102,7 @@ attribute_container_unregister(struct attribute_container *cont)list_del (&cont->node); out:spin_unlock (&cont->containers.k_lock); -up (&attribute_container_mutex); +mutex_unlock (&attribute_container_mutex);return retval; }
@@ -145,7 +145,7 @@ attribute_container_add_device(struct device *dev, {struct attribute_container *cont; -down (&attribute_container_mutex); +mutex_lock (&attribute_container_mutex);list_for_each_entry (cont, &attribute_container_list, node) {struct internal_container *ic;
@@ -173,7 +173,7 @@ attribute_container_add_device(struct device *dev,attribute_container_add_class_device (&ic->classdev);klist_add_tail (&ic->node, &cont->containers); } -up (&attribute_container_mutex); +mutex_unlock (&attribute_container_mutex); }/* FIXME: can't break out of this unless klist_iter_exit is also
@@ -211,7 +211,7 @@ attribute_container_remove_device(struct device *dev, {struct attribute_container *cont; -down (&attribute_container_mutex); +mutex_lock (&attribute_container_mutex);list_for_each_entry (cont, &attribute_container_list, node) {struct internal_container *ic;struct klist_iter iter;
@@ -234,7 +234,7 @@ attribute_container_remove_device(struct device *dev, } } } -up (&attribute_container_mutex); +mutex_unlock (&attribute_container_mutex); }/**
@@ -255,7 +255,7 @@ attribute_container_device_trigger(struct device *dev, {struct attribute_container *cont; -down (&attribute_container_mutex); +mutex_lock (&attribute_container_mutex);list_for_each_entry (cont, &attribute_container_list, node) {struct internal_container *ic;struct klist_iter iter;
@@ -273,7 +273,7 @@ attribute_container_device_trigger(struct device *dev,fn (cont, dev, &ic->classdev); } } -up (&attribute_container_mutex); +mutex_unlock (&attribute_container_mutex); }/**
@@ -295,12 +295,12 @@ attribute_container_trigger(struct device *dev, {struct attribute_container *cont; -down (&attribute_container_mutex); +mutex_lock (&attribute_container_mutex);list_for_each_entry (cont, &attribute_container_list, node) {if (cont->match (cont, dev))fn (cont, dev); } -up (&attribute_container_mutex); +mutex_unlock (&attribute_container_mutex); }/**
Signature · 1 line
1.5.1.2
PATCH 46/46 dev_dbg: check dev_dbg() arguments
From: Dan Williams <[email protected]>
Duplicate what Zach Brown did for pr_debug in commit 8b2a1fd1b394c60eaa2587716102dd5e9b4e5990
--- drivers/usb/core/hub.c | 4 +--- drivers/usb/host/ohci-hcd.c | 6 ------ include/linux/device.h | 6 +++++- 3 files changed, 6 insertions(+), 10 deletions(-)
drivers/usb/core/hub.c +1 -3
@@ -119,8 +119,7 @@ MODULE_PARM_DESC(use_both_schemes, "first one fails"); -#ifdef DEBUG -static inline char *portspeed (int portstatus) +static inline char *portspeed (int portstatus) {if (portstatus & (1 <<USB_PORT_FEAT_HIGHSPEED ))return "480 Mb/s" ;
@@ -129,7 +128,6 @@ static inline char *portspeed (int portstatus)else return "12 Mb/s" ; } -#endif /* Note that hdev or one of its children must be locked! */ static inline struct usb_hub *hdev_to_hub (struct usb_device *hdev)
drivers/usb/host/ohci-hcd.c +0 -6
@@ -486,9 +486,6 @@ static int ohci_run (struct ohci_hcd *ohci)* or if bus glue did the same (e.g. for PCI add-in cards with * PCI PM support). */ -ohci_dbg (ohci,"resetting from state '%s', control = 0x%x\n" , -hcfs2string (ohci->hc_control &OHCI_CTRL_HCFS ), -ohci_readl (ohci, &ohci->regs->control));if ((ohci->hc_control &OHCI_CTRL_RWC ) !=0 && !device_may_wakeup (hcd->self.controller))device_init_wakeup (hcd->self.controller,1 );
@@ -744,9 +741,6 @@ static void ohci_stop (struct usb_hcd *hcd) {struct ohci_hcd *ohci =hcd_to_ohci (hcd); -ohci_dbg (ohci,"stop %s controller (state 0x%02x)\n" , -hcfs2string (ohci->hc_control &OHCI_CTRL_HCFS ), - hcd->state);ohci_dump (ohci,1 );flush_scheduled_work ();
include/linux/device.h +5 -1
@@ -571,7 +571,11 @@ extern const char *dev_driver_string(struct device *dev); #define dev_dbg(dev, format, arg...) \ dev_printk(KERN_DEBUG , dev , format , ## arg)#else -#define dev_dbg(dev, format, arg...) do { (void)(dev); } while (0) +static inline int __attribute__ ((format (printf,2 ,3 ))) +dev_dbg (struct device * dev,const char * fmt, ...) +{ +return 0 ; +}#endif #define dev_err(dev, format, arg...) \
Signature · 1 line
1.5.1.2
Re: [PATCH 28/46] PHY: remove rwsem use from phy core
In reply to Greg Kroah-HartmanQuoted 6 lines · Greg Kroah-Hartman
The subsystem rwsem is not used by the driver core at all, so the use of it in the phy code doesn't make any sense. They might possibly want to use a local lock, but I am unsure about that.
Cc netdev <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>
Quoted 1 line
---
I think I copied that code from elsewhere without truly understanding it.
*bows head in shame*
As such, I have no objection to this patch unless someone says it breaks their board. :)
Quoted 74 lines
drivers/net/phy/fixed.c | 6 ------ drivers/net/phy/phy_device.c | 9 +-------- 2 files changed, 1 insertions(+), 14 deletions(-)drivers/net/phy/fixed.c +0
-6@@ -276,21 +276,15 @@ static int fixed_mdio_register_device(intnumber, int speed, int duplex) artificially, we are binding the driver here by hand; it will be the same for all the fixed phys anyway. */ -down_write (&phydev->dev.bus->subsys.rwsem); - phydev->dev.driver = &fixed_mdio_driver.driver; err = phydev->dev.driver->probe (&phydev->dev);if (err <0 ) {printk (KERN_ERR "Phy %s: problems with fixed driver\n" ,phydev- >dev.bus_id); -up_write (&phydev->dev.bus->subsys.rwsem); goto probe_fail; } err =device_bind_driver (&phydev->dev); - -up_write (&phydev->dev.bus->subsys.rwsem); -if (err)drivers/net/phy/fixed.c +0
-0goto probe_fail;drivers/net/phy/phy_device.c +0
-4@@ -208,16 +208,12 @@ struct phy_device *phy_attach(structnet_device *dev, * exist, and we should use the genphy driver. */ if (NULL == d->driver) {int err; -down_write (&d->bus->subsys.rwsem); d->driver = &genphy_driver.driver; err = d->driver->probe (d); -if (err >=0 ) err =device_bind_driver (d); -up_write (&d->bus->subsys.rwsem); -if (err)return ERR_PTR (err);drivers/net/phy/phy_device.c +1
-4}@@ -258,11 +254,8 @@ void phy_detach(struct phy_device *phydev)* was using the generic driver), we unbind the device * from the generic driver so that there's a chance a * real driver could be loaded */ -if (phydev->dev.driver == &genphy_driver.driver) { -down_write (&phydev->dev.bus->subsys.rwsem); +if (phydev->dev.driver == &genphy_driver.driver)device_release_driver (&phydev->dev); -up_write (&phydev->dev.bus->subsys.rwsem); - } }EXPORT_SYMBOL (phy_detach);Signature · 6 lines
1.5.1.2 - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 4/46 Driver core: udev triggered device-driver binding
In reply to Greg Kroah-HartmanFrom: Kay Sievers <[email protected]>
We get two per-bus sysfs files:
ls-l /sys/subsystem/usb
drwxr-xr-x 2 root root 0 2007-02-16 16:42 devices
drwxr-xr-x 7 root root 0 2007-02-16 14:55 drivers
-rw-r--r-- 1 root root 4096 2007-02-16 16:42 drivers_autoprobe --w------- 1 root root 4096 2007-02-16 16:42 drivers_probe
The flag "drivers_autoprobe" controls the behavior of the bus to bind devices by default, or just initialize the device and leave it alone.
The command "drivers_probe" accepts a bus_id and the bus tries to bind a driver to this device.
Systems who want to control the driver binding with udev, switch off the bus initiated probing:
echo 0 > /sys/subsystem/usb/drivers_autoprobe
echo 0 > /sys/subsystem/pcmcia/drivers_autoprobe
...
and initiate the probing with udev rules like:
ACTION=="add", SUBSYSTEM=="usb", ATTR{subsystem/drivers_probe}="$kernel" ACTION=="add", SUBSYSTEM=="pcmcia", ATTR{subsystem/drivers_probe}="$kernel"
...
Custom driver binding can happen in earlier rules by something like:
ACTION=="add", SUBSYSTEM=="usb", \
ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678" \
ATTR{subsystem/drivers/<custom-driver>/bind}="$kernel"
This is intended to solve the modprobe.conf mess with "install-rules", custom bind/unbind-scripts and all the weird things people invented over the years. It should also provide the functionality "libusual" was supposed to do.
With udev, one can just write a udev rule to drive all USB-disks at the third port of USB-hub by the "ub" driver, and everything else by usb-storage. One can also instruct udev to bind different wireless drivers to identical cards - just selected by the pcmcia slot-number, and whatever ...
To use the mentioned rules, it needs udev version 106, to be able to write ATTR{}="$kernel" to sysfs files.
--- drivers/base/bus.c | 84 ++++++++++++++++++++++++++++++++++++++++++++--- include/linux/device.h | 34 +++++++++++-------- 2 files changed, 97 insertions(+), 21 deletions(-)
drivers/base/bus.c +78 -6
@@ -27,6 +27,9 @@#define to_driver (obj) container_of(obj, struct device_driver, kobj) +static int __must_check bus_rescan_devices_helper (struct device *dev, +void *data); +static ssize_t drv_attr_show (struct kobject * kobj,struct attribute * attr,char * buf) {
@@ -133,7 +136,6 @@ static decl_subsys(bus, &ktype_bus, NULL);#ifdef CONFIG_HOTPLUG -/* Manually detach a device from its associated driver. */ static int driver_helper (struct device *dev,void *data) {
@@ -199,6 +201,33 @@ static ssize_t driver_bind(struct device_driver *drv, } static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind); +static ssize_t show_drivers_autoprobe (struct bus_type *bus,char *buf) +{ +return sprintf (buf,"%d\n" , bus->drivers_autoprobe); +} + +static ssize_t store_drivers_autoprobe (struct bus_type *bus, +const char *buf,size_t count) +{ +if (buf[0 ] =='0' ) + bus->drivers_autoprobe =0 ; +else + bus->drivers_autoprobe =1 ; +return count; +} + +static ssize_t store_drivers_probe (struct bus_type *bus, +const char *buf,size_t count) +{ +struct device *dev; + + dev =bus_find_device (bus,NULL , (void *)buf, driver_helper); +if (!dev) +return -ENODEV ; +if (bus_rescan_devices_helper (dev,NULL ) !=0 ) +return -EINVAL ; +return count; +}#endif static struct device *next_device (struct klist_iter * i)
@@ -425,7 +454,8 @@ int bus_attach_device(struct device * dev)if (bus) { dev->is_registered =1 ; - ret =device_attach (dev); +if (bus->drivers_autoprobe) + ret =device_attach (dev);if (ret >=0 ) {klist_add_tail (&dev->knode_bus, &bus->klist_devices); ret =0 ;
@@ -515,9 +545,41 @@ static void remove_bind_files(struct device_driver *drv)driver_remove_file (drv, &driver_attr_bind);driver_remove_file (drv, &driver_attr_unbind); } + +static int add_probe_files (struct bus_type *bus) +{ +int retval; + + bus->drivers_probe_attr.attr.name ="drivers_probe" ; + bus->drivers_probe_attr.attr.mode =S_IWUSR ; + bus->drivers_probe_attr.attr.owner = bus->owner; + bus->drivers_probe_attr.store = store_drivers_probe; + retval =bus_create_file (bus, &bus->drivers_probe_attr); +if (retval) + goto out; + + bus->drivers_autoprobe_attr.attr.name ="drivers_autoprobe" ; + bus->drivers_autoprobe_attr.attr.mode =S_IWUSR |S_IRUGO ; + bus->drivers_autoprobe_attr.attr.owner = bus->owner; + bus->drivers_autoprobe_attr.show = show_drivers_autoprobe; + bus->drivers_autoprobe_attr.store = store_drivers_autoprobe; + retval =bus_create_file (bus, &bus->drivers_autoprobe_attr); +if (retval) +bus_remove_file (bus, &bus->drivers_probe_attr); +out: +return retval; +} + +static void remove_probe_files (struct bus_type *bus) +{ +bus_remove_file (bus, &bus->drivers_autoprobe_attr); +bus_remove_file (bus, &bus->drivers_probe_attr); +}#else static inline int add_bind_files (struct device_driver *drv) {return 0 ; }static inline void remove_bind_files (struct device_driver *drv) {} +static inline int add_probe_files (struct bus_type *bus) {return 0 ; } +static inline void remove_probe_files (struct bus_type *bus) {}#endif /**
@@ -541,9 +603,11 @@ int bus_add_driver(struct device_driver *drv)if ((error =kobject_register (&drv->kobj))) goto out_put_bus; - error =driver_attach (drv); -if (error) - goto out_unregister; +if (drv->bus->drivers_autoprobe) { + error =driver_attach (drv); +if (error) + goto out_unregister; + }klist_add_tail (&drv->knode_bus, &bus->klist_drivers);module_add_driver (drv->owner, drv);
@@ -762,6 +826,12 @@ int bus_register(struct bus_type * bus)klist_init (&bus->klist_devices, klist_devices_get, klist_devices_put);klist_init (&bus->klist_drivers,NULL ,NULL ); + + bus->drivers_autoprobe =1 ; + retval =add_probe_files (bus); +if (retval) + goto bus_probe_files_fail; + retval =bus_add_attrs (bus);if (retval) goto bus_attrs_fail;
@@ -770,6 +840,8 @@ int bus_register(struct bus_type * bus)return 0 ; bus_attrs_fail: +remove_probe_files (bus); +bus_probe_files_fail:kset_unregister (&bus->drivers); bus_drivers_fail:kset_unregister (&bus->devices);
@@ -779,7 +851,6 @@ out:return retval; } -/** * bus_unregister - remove a bus from the system * @bus: bus.
@@ -791,6 +862,7 @@ void bus_unregister(struct bus_type * bus) {pr_debug ("bus %s: unregistering\n" , bus->name);bus_remove_attrs (bus); +remove_probe_files (bus);kset_unregister (&bus->drivers);kset_unregister (&bus->devices);subsystem_unregister (&bus->subsys);
include/linux/device.h +19 -15
@@ -34,9 +34,24 @@ struct device;struct device_driver ;struct class ;struct class_device ; +struct bus_type ; + +struct bus_attribute { +struct attribute attr; +ssize_t (*show)(struct bus_type *,char * buf); +ssize_t (*store)(struct bus_type *,const char * buf,size_t count); +}; + +#define BUS_ATTR (_name,_mode,_show,_store) \ +struct bus_attribute bus_attr_##_name = __ATTR(_name,_mode,_show,_store) + +extern int __must_check bus_create_file (struct bus_type *, +struct bus_attribute *); +extern void bus_remove_file (struct bus_type *,struct bus_attribute *);struct bus_type {const char * name; +struct module * owner;struct subsystem subsys;struct kset drivers;
@@ -49,6 +64,8 @@ struct bus_type {struct bus_attribute * bus_attrs;struct device_attribute * dev_attrs;struct driver_attribute * drv_attrs; +struct bus_attribute drivers_autoprobe_attr; +struct bus_attribute drivers_probe_attr;int (*match)(struct device * dev,struct device_driver * drv); int (*uevent)(struct device *dev, char **envp,
@@ -61,6 +78,8 @@ struct bus_type {int (*suspend_late)(struct device * dev,pm_message_t state);int (*resume_early)(struct device * dev);int (*resume)(struct device * dev); + + unsigned int drivers_autoprobe:1; };extern int __must_check bus_register (struct bus_type * bus);
@@ -102,21 +121,6 @@ extern int bus_unregister_notifier(struct bus_type *bus,#define BUS_NOTIFY_UNBIND_DRIVER 0x00000004/* driver about to be unbound */ -/* sysfs interface for exporting bus attributes */ - -struct bus_attribute { -struct attribute attr; -ssize_t (*show)(struct bus_type *,char * buf); -ssize_t (*store)(struct bus_type *,const char * buf,size_t count); -}; - -#define BUS_ATTR (_name,_mode,_show,_store) \ -struct bus_attribute bus_attr_##_name = __ATTR(_name,_mode,_show,_store) - -extern int __must_check bus_create_file (struct bus_type *, -struct bus_attribute *); -extern void bus_remove_file (struct bus_type *,struct bus_attribute *); -struct device_driver {const char * name;struct bus_type * bus;
Signature · 1 line
1.5.1.2