diff options
author | Al Viro <viro@ftp.linux.org.uk> | 2007-07-23 11:21:34 +0100 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-07-23 13:35:23 -0400 |
commit | 3b0d71170d37878bbb1203ebc3f92e36d6151a80 (patch) | |
tree | f2371d2114c40f622a3f037df04d4e1684353171 /drivers/misc/asus-laptop.c | |
parent | 3cc2649b879f0e83fd51b14c82bad5f8f208591e (diff) | |
download | blackbird-op-linux-3b0d71170d37878bbb1203ebc3f92e36d6151a80.tar.gz blackbird-op-linux-3b0d71170d37878bbb1203ebc3f92e36d6151a80.zip |
ACPI: asus-laptop: Fix failure exits
> Subject : drivers/misc/asus-laptop.c:*: error: 'struct led_classdev' has no member named 'class_dev'
> References : http://lkml.org/lkml/2007/7/22/299
> Submitter : Gabriel C <nix.or.die@googlemail.com>
Fallout from f8a7c6fe14f556ca8eeddce258cb21392d0c3a2f. However, looking
at it shows that checks done in ASUS_LED_UNREGISTER() can't trigger
at all (we never get to asus_led_exit() if registration fails) and
if that registration fails, we actually leak stuff. IOW, it's worse
than just replacing class_dev with dev in there - the tests themselves
had been papering over the lousy cleanup logics.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/misc/asus-laptop.c')
-rw-r--r-- | drivers/misc/asus-laptop.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index f75306059971..6b89854bd3ff 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c @@ -1067,19 +1067,16 @@ static void asus_backlight_exit(void) } #define ASUS_LED_UNREGISTER(object) \ - if(object##_led.class_dev \ - && !IS_ERR(object##_led.class_dev)) \ - led_classdev_unregister(&object##_led) + led_classdev_unregister(&object##_led) static void asus_led_exit(void) { + destroy_workqueue(led_workqueue); ASUS_LED_UNREGISTER(mled); ASUS_LED_UNREGISTER(tled); ASUS_LED_UNREGISTER(pled); ASUS_LED_UNREGISTER(rled); ASUS_LED_UNREGISTER(gled); - - destroy_workqueue(led_workqueue); } static void __exit asus_laptop_exit(void) @@ -1135,29 +1132,42 @@ static int asus_led_init(struct device *dev) rv = ASUS_LED_REGISTER(mled, dev); if (rv) - return rv; + goto out; rv = ASUS_LED_REGISTER(tled, dev); if (rv) - return rv; + goto out1; rv = ASUS_LED_REGISTER(rled, dev); if (rv) - return rv; + goto out2; rv = ASUS_LED_REGISTER(pled, dev); if (rv) - return rv; + goto out3; rv = ASUS_LED_REGISTER(gled, dev); if (rv) - return rv; + goto out4; led_workqueue = create_singlethread_workqueue("led_workqueue"); if (!led_workqueue) - return -ENOMEM; + goto out5; return 0; +out5: + rv = -ENOMEM; + ASUS_LED_UNREGISTER(gled); +out4: + ASUS_LED_UNREGISTER(pled); +out3: + ASUS_LED_UNREGISTER(rled); +out2: + ASUS_LED_UNREGISTER(tled); +out1: + ASUS_LED_UNREGISTER(mled); +out: + return rv; } static int __init asus_laptop_init(void) |