Driver core patches for 2.6.21-rc1
Subsystems (6)
PATCH 1/1 Driver core patches for 2.6.21-rc1
Here are some driver core fixes for 2.6.21-rc1.
It fixes up some problems due to the pcmcia changes I did in the last round of driver core changes, removes an unused function, and backs out the kmod changes as there was a nasty loop for people who use networking as a module. There's some other bugfixes here, and some powermanagement documentation updates and clarifications (from -mm).
All of these have been in the -mm tree.
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
drivers/base/class.c | 42 -------------- drivers/base/core.c | 31 ++++++++++- drivers/pcmcia/hd64465_ss.c | 2 +- drivers/pcmcia/m32r_cfc.c | 2 +- drivers/pcmcia/m8xx_pcmcia.c | 2 +- drivers/pcmcia/omap_cf.c | 2 +- drivers/pcmcia/rsrc_mgr.c | 2 +- drivers/pcmcia/vrc4171_card.c | 2 +- fs/sysfs/sysfs.h | 11 ++++ include/linux/device.h | 2 - include/linux/kmod.h | 2 - include/linux/pm.h | 37 ++++++++++++- include/linux/sysfs.h | 13 +---- kernel/kmod.c | 120 ----------------------------------------- kernel/module.c | 32 ++++++------ kernel/params.c | 1 - kernel/power/main.c | 5 ++- 17 files changed, 103 insertions(+), 205 deletions(-)
---------------
Adam J. Richter (1):
sysfs: move struct sysfs_dirent to private header
Adrian Bunk (1):
make kernel/kmod.c:kmod_mk static
Greg Kroah-Hartman (2):
Driver core: remove class_device_rename
Revert "Driver core: let request_module() send a /sys/modules/kmod/-uevent"
James Simmons (1):
Driver core: fix error by cleanup up symlinks properly
Johannes Berg (2):
power management: no valid states w/o pm_ops power management: fix struct layout and docs
Manuel Lauss (1):
Driver core: more fallout from class_device changes for pcmcia
Mike Galbraith (1):
driver core: refcounting fix
PATCH 1/9 Driver core: remove class_device_rename
No one uses it, and it wasn't exported to modules, so remove it. The only other user of it was the network code, which is now converted to use struct device instead.
--- drivers/base/class.c | 42 ------------------------------------------ include/linux/device.h | 2 -- 2 files changed, 0 insertions(+), 44 deletions(-)
drivers/base/class.c +0 -42
@@ -840,48 +840,6 @@ void class_device_destroy(struct class *cls, dev_t devt)class_device_unregister (class_dev); } -int class_device_rename (struct class_device *class_dev,char *new_name) -{ -int error =0 ; -char *old_class_name =NULL , *new_class_name =NULL ; - - class_dev =class_device_get (class_dev); -if (!class_dev) -return -EINVAL ; - -pr_debug ("CLASS: renaming '%s' to '%s'\n" , class_dev->class_id, - new_name); - -#ifdef CONFIG_SYSFS_DEPRECATED -if (class_dev->dev) - old_class_name =make_class_name (class_dev->class->name, - &class_dev->kobj); -#endif - -strlcpy (class_dev->class_id, new_name,KOBJ_NAME_LEN ); - - error =kobject_rename (&class_dev->kobj, new_name); - -#ifdef CONFIG_SYSFS_DEPRECATED -if (class_dev->dev) { - new_class_name =make_class_name (class_dev->class->name, - &class_dev->kobj); -if (new_class_name) -sysfs_create_link (&class_dev->dev->kobj, - &class_dev->kobj, new_class_name); -if (old_class_name) -sysfs_remove_link (&class_dev->dev->kobj, - old_class_name); - } -#endif -class_device_put (class_dev); - -kfree (old_class_name); -kfree (new_class_name); - -return error; -} -struct class_device *class_device_get (struct class_device *class_dev) {if (class_dev)
include/linux/device.h +0 -2
@@ -294,8 +294,6 @@ extern void class_device_initialize(struct class_device *);extern int __must_check class_device_add (struct class_device *);extern void class_device_del (struct class_device *); -extern int class_device_rename (struct class_device *,char *); -extern struct class_device *class_device_get (struct class_device *);extern void class_device_put (struct class_device *);
Signature · 1 line
1.5.0.1
PATCH 2/9 driver core: refcounting fix
From: Mike Galbraith <[email protected]>
Fix a reference counting bug exposed by commit 725522b5453dd680412f2b6463a988e4fd148757. If driver.mod_name exists, we take a reference in module_add_driver(), and never release it. Undo that reference in module_remove_driver().
--- kernel/module.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
kernel/module.c +6 -0
@@ -2425,6 +2425,12 @@ void module_remove_driver(struct device_driver *drv) kfree(driver_name); } } +/* +* Undo the additional reference we added in module_add_driver() +* via kset_find_obj() +*/ +if (drv->mod_name) +kobject_put (&drv->kobj); }EXPORT_SYMBOL (module_remove_driver);#endif
Signature · 1 line
1.5.0.1
PATCH 3/9 sysfs: move struct sysfs_dirent to private header
From: Adam J. Richter <[email protected]>
struct sysfs_dirent is private to the fs/sysfs/ subtree. It is not even referenced as an opaque structure outside of that subtree.
The following patch moves the declaration from include/linux/sysfs.h to fs/sysfs/sysfs.h, making it clearer that nothing else in the kernel dereferences it.
I have been running this patch for years. Please integrate and forward upstream if there are no objections.
From: "Adam J. Richter" <[email protected]>
--- fs/sysfs/sysfs.h | 11 +++++++++++ include/linux/sysfs.h | 13 +------------ 2 files changed, 12 insertions(+), 12 deletions(-)
fs/sysfs/sysfs.h +11 -0
@@ -1,3 +1,14 @@ +struct sysfs_dirent { +atomic_t s_count; +struct list_head s_sibling; +struct list_head s_children; +void * s_element; +int s_type; +umode_t s_mode; +struct dentry * s_dentry; +struct iattr * s_iattr; +atomic_t s_event; +};extern struct vfsmount * sysfs_mount;extern struct kmem_cache *sysfs_dir_cachep;
include/linux/sysfs.h +1 -12
@@ -17,6 +17,7 @@struct kobject ;struct module ;struct nameidata ; +struct dentry ;struct attribute {const char * name;
@@ -68,18 +69,6 @@ struct sysfs_ops {ssize_t (*store)(struct kobject *,struct attribute *,const char *,size_t ); }; -struct sysfs_dirent { -atomic_t s_count; -struct list_head s_sibling; -struct list_head s_children; -void * s_element; -int s_type; -umode_t s_mode; -struct dentry * s_dentry; -struct iattr * s_iattr; -atomic_t s_event; -}; -#define SYSFS_ROOT 0x0001#define SYSFS_DIR 0x0002#define SYSFS_KOBJ_ATTR 0x0004
Signature · 1 line
1.5.0.1
PATCH 4/9 Driver core: more fallout from class_device changes for pcmcia
From: Manuel Lauss <[email protected]>
More fallout from the PCMCIA class_device changes.
The first hunk is run-tested on SH-4, the others are converted in the spirit of the original conversion.
--- drivers/pcmcia/hd64465_ss.c | 2 +- drivers/pcmcia/m32r_cfc.c | 2 +- drivers/pcmcia/m8xx_pcmcia.c | 2 +- drivers/pcmcia/omap_cf.c | 2 +- drivers/pcmcia/rsrc_mgr.c | 2 +- drivers/pcmcia/vrc4171_card.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-)
drivers/pcmcia/hd64465_ss.c +1 -1
@@ -907,7 +907,7 @@ static int __init init_hs(void)for (i=0 ; i<HS_MAX_SOCKETS ; i++) {unsigned int ret; - hs_sockets[i].socket.dev.dev = &hd64465_device.dev; + hs_sockets[i].socket.dev.parent = &hd64465_device.dev; hs_sockets[i].number = i; ret =pcmcia_register_socket (&hs_sockets[i].socket);if (ret && i)
drivers/pcmcia/m32r_cfc.c +1 -1
@@ -760,7 +760,7 @@ static int __init init_m32r_pcc(void)/* Set up interrupt handler(s) */ for (i =0 ; i < pcc_sockets ; i++) { - socket[i].socket.dev.dev = &pcc_device.dev; + socket[i].socket.dev.parent = &pcc_device.dev; socket[i].socket.ops = &pcc_operations; socket[i].socket.resource_ops = &pccard_nonstatic_ops; socket[i].socket.owner =THIS_MODULE ;
drivers/pcmcia/m8xx_pcmcia.c +1 -1
@@ -1321,7 +1321,7 @@ static int __init m8xx_init(void) socket[i].socket.ops = &m8xx_services; socket[i].socket.resource_ops = &pccard_iodyn_ops; socket[i].socket.cb_dev =NULL ; - socket[i].socket.dev.dev = &m8xx_device.dev; + socket[i].socket.dev.parent = &m8xx_device.dev; }for (i =0 ; i <PCMCIA_SOCKETS_NO ; i++)
drivers/pcmcia/omap_cf.c +1 -1
@@ -291,7 +291,7 @@ static int __devinit omap_cf_probe(struct device *dev) omap_cf_present() ? "present" : "(not present)"); cf->socket.owner =THIS_MODULE ; - cf->socket.dev.dev = dev; + cf->socket.dev.parent = dev; cf->socket.ops = &omap_cf_ops; cf->socket.resource_ops = &pccard_static_ops; cf->socket.features =SS_CAP_PCCARD |SS_CAP_STATIC_MAP
drivers/pcmcia/rsrc_mgr.c +1 -1
@@ -232,7 +232,7 @@ static struct resource *iodyn_find_io_region(unsigned long base, int num, unsigned long align, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_IO, - s->dev.class_id); + s->dev.bus_id);struct pcmcia_align_data data;unsigned long min = base;int ret;
drivers/pcmcia/vrc4171_card.c +1 -1
@@ -596,7 +596,7 @@ static int __devinit vrc4171_add_sockets(void) }sprintf (socket->name,"NEC VRC4171 Card Slot %1c" ,'A' + slot); - socket->pcmcia_socket.dev.dev = &vrc4171_card_device.dev; + socket->pcmcia_socket.dev.parent = &vrc4171_card_device.dev; socket->pcmcia_socket.ops = &vrc4171_pccard_operations; socket->pcmcia_socket.owner =THIS_MODULE ;
Signature · 1 line
1.5.0.1
PATCH 5/9 power management: no valid states w/o pm_ops
From: Johannes Berg <[email protected]>
Change /sys/power/state to not advertise any valid states (except for disk if SOFTWARE_SUSPEND is enabled) when no pm_ops have been set so userspace can easily discover what states should be available.
--- kernel/power/main.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
kernel/power/main.c +4 -1
@@ -167,7 +167,10 @@ static inline int valid_state(suspend_state_t state)if (state ==PM_SUSPEND_DISK )return 1 ; -if (pm_ops && pm_ops->valid && !pm_ops->valid (state)) +/* all other states need lowlevel support and need to be +* valid to the lowlevel implementation, no valid callback +* implies that all are valid. */ +if (!pm_ops || (pm_ops->valid && !pm_ops->valid (state)))return 0 ;return 1 ; }
Signature · 1 line
1.5.0.1
PATCH 6/9 power management: fix struct layout and docs
From: Johannes Berg <[email protected]>
Because the pm ops in powermac are obviously not using them as intended, I added documentation for it in kernel-doc format.
Reordering the fields in struct pm_ops not only makes the output of kernel-doc make more sense but also removes a hole from the structure on 64-bit platforms.
--- include/linux/pm.h | 37 +++++++++++++++++++++++++++++++++++-- 1 files changed, 35 insertions(+), 2 deletions(-)
include/linux/pm.h +35 -2
@@ -120,15 +120,48 @@ typedef int __bitwise suspend_disk_method_t;#define PM_DISK_TESTPROC ((__force suspend_disk_method_t) 6)#define PM_DISK_MAX ((__force suspend_disk_method_t) 7) +/** +* struct pm_ops - Callbacks for managing platform dependent suspend states. +* @valid: Callback to determine whether the given state can be entered. +* If %CONFIG_SOFTWARE_SUSPEND is set then %PM_SUSPEND_DISK is +* always valid and never passed to this call. +* If not assigned, all suspend states are advertised as valid +* in /sys/power/state (but can still be rejected by prepare or enter.) +* +* @prepare: Prepare the platform for the given suspend state. Can return a +* negative error code if necessary. +* +* @enter: Enter the given suspend state, must be assigned. Can return a +* negative error code if necessary. +* +* @finish: Called when the system has left the given state and all devices +* are resumed. The return value is ignored. +* +* @pm_disk_mode: Set to the disk method that the user should be able to +* configure for suspend-to-disk. Since %PM_DISK_SHUTDOWN, +* %PM_DISK_REBOOT, %PM_DISK_TEST and %PM_DISK_TESTPROC +* are always allowed, currently only %PM_DISK_PLATFORM +* makes sense. If the user then choses %PM_DISK_PLATFORM, +* the @prepare call will be called before suspending to disk +* (if present), the @enter call should be present and will +* be called after all state has been saved and the machine +* is ready to be shut down/suspended/..., and the @finish +* callback is called after state has been restored. All +* these calls are called with %PM_SUSPEND_DISK as the state. +*/ struct pm_ops { -suspend_disk_method_t pm_disk_mode;int (*valid)(suspend_state_t state);int (*prepare)(suspend_state_t state);int (*enter)(suspend_state_t state);int (*finish)(suspend_state_t state); +suspend_disk_method_t pm_disk_mode; }; -extern void pm_set_ops (struct pm_ops *); +/** +* pm_set_ops - set platform dependent power management ops +* @pm_ops: The new power management operations to set. +*/ +extern void pm_set_ops (struct pm_ops *pm_ops);extern struct pm_ops *pm_ops;extern int pm_suspend (suspend_state_t state);
Signature · 1 line
1.5.0.1
PATCH 7/9 make kernel/kmod.c:kmod_mk static
From: Adrian Bunk <[email protected]>
This patch makes the needlessly global struct kmod_mk static.
--- kernel/kmod.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/kmod.c +1 -1
@@ -48,7 +48,7 @@ static struct workqueue_struct *khelper_wq;modprobe_path is set via /proc/sys. */ char modprobe_path[KMOD_PATH_LEN ] ="/sbin/modprobe" ; -struct module_kobject kmod_mk; +static struct module_kobject kmod_mk;/** * request_module - try to load a kernel module
Signature · 1 line
1.5.0.1
PATCH 8/9 Driver core: fix error by cleanup up symlinks properly
From: James Simmons <[email protected]>
When a device fails to register the class symlinks where not cleaned up. This left a symlink in the /sys/class/"device"/ directory that pointed to no where. This caused the sysfs_follow_link Oops I reported earlier. This patch cleanups up the symlink. Please apply. Thank you.
Signed-Off: James Simmons <[email protected]>
--- drivers/base/core.c | 31 ++++++++++++++++++++++++++++++- 1 files changed, 30 insertions(+), 1 deletions(-)
drivers/base/core.c +30 -1
@@ -637,12 +637,41 @@ int device_add(struct device *dev) BUS_NOTIFY_DEL_DEVICE, dev);device_remove_groups (dev); GroupError: -device_remove_attrs (dev); +device_remove_attrs (dev); AttrsError:if (dev->devt_attr) {device_remove_file (dev, dev->devt_attr);kfree (dev->devt_attr); } + +if (dev->class) { +sysfs_remove_link (&dev->kobj,"subsystem" ); +/* If this is not a "fake" compatible device, remove the +* symlink from the class to the device. */ +if (dev->kobj.parent != &dev->class->subsys.kset.kobj) +sysfs_remove_link (&dev->class->subsys.kset.kobj, + dev->bus_id); +#ifdef CONFIG_SYSFS_DEPRECATED +if (parent) { +char *class_name =make_class_name (dev->class->name, + &dev->kobj); +if (class_name) +sysfs_remove_link (&dev->parent->kobj, + class_name); +kfree (class_name); +sysfs_remove_link (&dev->kobj,"device" ); + } +#endif + +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); attrError:
Signature · 1 line
1.5.0.1
PATCH 9/9 Revert "Driver core: let request_module() send a /sys/modules/kmod/-uevent"
This reverts commit c353c3fb0700a3c17ea2b0237710a184232ccd7f.
It turns out that we end up with a loop trying to load the unix module and calling netfilter to do that. Will redo the patch later to not have this loop.
--- include/linux/kmod.h | 2 - kernel/kmod.c | 120 -------------------------------------------------- kernel/module.c | 26 ++++------- kernel/params.c | 1 - 4 files changed, 10 insertions(+), 139 deletions(-)
include/linux/kmod.h +0 -2
@@ -28,10 +28,8 @@#ifdef CONFIG_KMOD /* modprobe exit status on success, -ve on error. Return value * usually useless though. */ -extern void kmod_sysfs_init (void );extern int request_module (const char * name, ...) __attribute__ ((format (printf,1 ,2 )));#else -static inline void kmod_sysfs_init (void ) {};static inline int request_module (const char * name, ...) {return -ENOSYS ; }#endif
kernel/kmod.c +0 -120
153 lines not on this page · raw message
kernel/module.c +10 -16
@@ -653,11 +653,20 @@ static void wait_for_zero_refcount(struct module *mod)mutex_lock (&module_mutex); } -int delete_module (const char *name,unsigned int flags) +asmlinkage long +sys_delete_module (const char __user *name_user,unsigned int flags) {struct module *mod; +char name[MODULE_NAME_LEN ];int ret, forced =0 ; +if (!capable (CAP_SYS_MODULE )) +return -EPERM ; + +if (strncpy_from_user (name, name_user,MODULE_NAME_LEN -1 ) <0 ) +return -EFAULT ; + name[MODULE_NAME_LEN -1 ] ='\0' ; +if (mutex_lock_interruptible (&module_mutex) !=0 )return -EINTR ;
@@ -718,21 +727,6 @@ int delete_module(const char *name, unsigned int flags)return ret; } -asmlinkage long -sys_delete_module (const char __user *name_user,unsigned int flags) -{ -char name[MODULE_NAME_LEN ]; - -if (!capable (CAP_SYS_MODULE )) -return -EPERM ; - -if (strncpy_from_user (name, name_user,MODULE_NAME_LEN -1 ) <0 ) -return -EFAULT ; - name[MODULE_NAME_LEN -1 ] ='\0' ; - -return delete_module (name, flags); -} -static void print_unload_info (struct seq_file *m,struct module *mod) {struct module_use *use;
kernel/params.c +0 -1
@@ -707,7 +707,6 @@ static int __init param_sysfs_init(void) }param_sysfs_builtin (); -kmod_sysfs_init ();return 0 ; }
Signature · 1 line
1.5.0.1
Re: [PATCH 8/9] Driver core: fix error by cleanup up symlinks properly
In reply to Greg Kroah-HartmanQuoted 38 lines · Greg Kroah-Hartman
From: James Simmons <[email protected]>
When a device fails to register the class symlinks where not cleaned up. This left a symlink in the /sys/class/"device"/ directory that pointed to no where. This caused the
sysfs_follow_linkOops I reported earlier. This patch cleanups up the symlink. Please apply. Thank you.Signed-Off: James Simmons <[email protected]>
Signed-off-by Greg Kroah-Hartman <[email protected]>--- drivers/base/core.c | 31 ++++++++++++++++++++++++++++++- 1 files changed, 30 insertions(+), 1 deletions(-)drivers/base/core.c +11
-1@@ -637,12 +637,41 @@ int device_add(struct device *dev) BUS_NOTIFY_DEL_DEVICE, dev);device_remove_groups (dev); GroupError: -device_remove_attrs (dev); +device_remove_attrs (dev); AttrsError:if (dev->devt_attr) {device_remove_file (dev, dev->devt_attr);kfree (dev->devt_attr); } + +if (dev->class) { +sysfs_remove_link (&dev->kobj,"subsystem" ); +/* If this is not a "fake" compatible device, remove the +* symlink from the class to the device. */ +if (dev->kobj.parent != &dev->class->subsys.kset.kobj) +sysfs_remove_link (&dev->class->subsys.kset.kobj, + dev->bus_id); +#ifdef CONFIG_SYSFS_DEPRECATED +if (parent) {
drivers/base/core.c int device_add(struct device *dev) · line 665
Quoted 10 lines
drivers/base/core.c +10
-0+char *class_name =make_class_name (dev->class->name, + &dev->kobj); +if (class_name) +sysfs_remove_link (&dev->parent->kobj, + class_name); +kfree (class_name); + sysfs_remove_link(&dev->kobj, "device"); + } +#endif +
<<<<< block begin
drivers/base/core.c int device_add(struct device *dev) · line 673
Quoted 8 lines
drivers/base/core.c +8
-0+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);
<<<<<< block end
May be i've missed something, but i'm confuesd a litle bit.
For example if error happens while device_pm_add() we jump to label "PMError" and code from block above will be executed (device will be remove from list), but this device wasn't added to this list yet!
Quoted 12 lines
drivers/base/core.c +1
-0+ } ueventattrError:device_remove_file (dev, &dev->uevent_attr); attrError:Signature · 7 lines
1.5.0.1 - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
PATCH 1/1 driver core: fix device_add error path
Quoted 51 lines · Dmitriy Monakhov
Quoted 38 lines · Greg Kroah-Hartman
From: James Simmons <[email protected]>
When a device fails to register the class symlinks where not cleaned up. This left a symlink in the /sys/class/"device"/ directory that pointed to no where. This caused the
sysfs_follow_linkOops I reported earlier. This patch cleanups up the symlink. Please apply. Thank you.Signed-Off: James Simmons <[email protected]>
Signed-off-by Greg Kroah-Hartman <[email protected]>--- drivers/base/core.c | 31 ++++++++++++++++++++++++++++++- 1 files changed, 30 insertions(+), 1 deletions(-)drivers/base/core.c +11
-1@@ -637,12 +637,41 @@ int device_add(struct device *dev) BUS_NOTIFY_DEL_DEVICE, dev);device_remove_groups (dev); GroupError: -device_remove_attrs (dev); +device_remove_attrs (dev); AttrsError:if (dev->devt_attr) {device_remove_file (dev, dev->devt_attr);kfree (dev->devt_attr); } + +if (dev->class) { +sysfs_remove_link (&dev->kobj,"subsystem" ); +/* If this is not a "fake" compatible device, remove the +* symlink from the class to the device. */ +if (dev->kobj.parent != &dev->class->subsys.kset.kobj) +sysfs_remove_link (&dev->class->subsys.kset.kobj, + dev->bus_id); +#ifdef CONFIG_SYSFS_DEPRECATED +if (parent) {drivers/base/core.c int device_add(struct device *dev) · line 665
Quoted 10 lines
drivers/base/core.c +10
-0+char *class_name =make_class_name (dev->class->name, + &dev->kobj); +if (class_name) +sysfs_remove_link (&dev->parent->kobj, + class_name); +kfree (class_name); + sysfs_remove_link(&dev->kobj, "device"); + } +#endif +<<<<< block begin
Quoted 13 lines
drivers/base/core.c int device_add(struct device *dev) · line 673
Quoted 8 lines
drivers/base/core.c +8
-0+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);<<<<<< block end
May be i've missed something, but i'm confuesd a litle bit.
For example if error happens whiledevice_pm_add()we jump to label "PMError" and code from block above will be executed (device will be remove from list), but this device wasn't added to this list yet!
I've check it one more time, code it really broken!, and i think i understand how this can happen ....
it look like full code chunck was copy-pasted from device_del(), but in case of device_add() error path, device was't added to dev->class->devices list yet. Folowing patch fix this copy-paste error:
[PATCH] driver core: fix device_add error path
- 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
@@ -684,15 +684,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.0.1