diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2009-05-28 17:24:07 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-05-28 17:24:07 -0400 |
commit | 5c8563d773c0e9f0ac2a552e84806decd98ce732 (patch) | |
tree | b771f23cd143c4efb4f140f8ef98204cf9c6ef93 | |
parent | 086a377edc969aea6c761176a7e4ff68f264d6fe (diff) |
Driver Core: do not oops when driver_unregister() is called for unregistered drivers
We also fix a problem with cleaning up properly when initializing
drivers and devices, so checks like this will work successfully.
Portions of the patch by Linus and Greg and Ingo.
Reported-by: Ozan Çağlayan <ozan@pardus.org.tr>
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/base/bus.c | 4 | ||||
-rw-r--r-- | drivers/base/core.c | 5 | ||||
-rw-r--r-- | drivers/base/driver.c | 4 |
3 files changed, 11 insertions, 2 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index dc030f1f00f1..c6599618523e 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -700,8 +700,10 @@ int bus_add_driver(struct device_driver *drv) | |||
700 | } | 700 | } |
701 | 701 | ||
702 | kobject_uevent(&priv->kobj, KOBJ_ADD); | 702 | kobject_uevent(&priv->kobj, KOBJ_ADD); |
703 | return error; | 703 | return 0; |
704 | out_unregister: | 704 | out_unregister: |
705 | kfree(drv->p); | ||
706 | drv->p = NULL; | ||
705 | kobject_put(&priv->kobj); | 707 | kobject_put(&priv->kobj); |
706 | out_put_bus: | 708 | out_put_bus: |
707 | bus_put(bus); | 709 | bus_put(bus); |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 4aa527b8a913..1977d4beb89e 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -879,7 +879,7 @@ int device_add(struct device *dev) | |||
879 | } | 879 | } |
880 | 880 | ||
881 | if (!dev_name(dev)) | 881 | if (!dev_name(dev)) |
882 | goto done; | 882 | goto name_error; |
883 | 883 | ||
884 | pr_debug("device: '%s': %s\n", dev_name(dev), __func__); | 884 | pr_debug("device: '%s': %s\n", dev_name(dev), __func__); |
885 | 885 | ||
@@ -978,6 +978,9 @@ done: | |||
978 | cleanup_device_parent(dev); | 978 | cleanup_device_parent(dev); |
979 | if (parent) | 979 | if (parent) |
980 | put_device(parent); | 980 | put_device(parent); |
981 | name_error: | ||
982 | kfree(dev->p); | ||
983 | dev->p = NULL; | ||
981 | goto done; | 984 | goto done; |
982 | } | 985 | } |
983 | 986 | ||
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index c51f11bb29ae..8ae0f63602e0 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
@@ -257,6 +257,10 @@ EXPORT_SYMBOL_GPL(driver_register); | |||
257 | */ | 257 | */ |
258 | void driver_unregister(struct device_driver *drv) | 258 | void driver_unregister(struct device_driver *drv) |
259 | { | 259 | { |
260 | if (!drv || !drv->p) { | ||
261 | WARN(1, "Unexpected driver unregister!\n"); | ||
262 | return; | ||
263 | } | ||
260 | driver_remove_groups(drv, drv->groups); | 264 | driver_remove_groups(drv, drv->groups); |
261 | bus_remove_driver(drv); | 265 | bus_remove_driver(drv); |
262 | } | 266 | } |