aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@ftp.linux.org.uk>2007-07-23 21:43:54 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-24 15:24:59 -0400
commitd316ee5787153765980ca0f55ee864ec883979ab (patch)
tree2fb761e5b33f63e80bc018cd19027ec88626e035
parentc51aea80a9fbb423b49d432e89e515257bb2b983 (diff)
Fix failure exits in asus-laptop
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> Michal Piotrowski <michal.k.k.piotrowski@gmail.com> Cc: Corentin Chary <corentincj@iksaif.net> Cc: Karol Kozimor <sziwan@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/misc/asus-laptop.c32
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)
1067} 1067}
1068 1068
1069#define ASUS_LED_UNREGISTER(object) \ 1069#define ASUS_LED_UNREGISTER(object) \
1070 if(object##_led.class_dev \ 1070 led_classdev_unregister(&object##_led)
1071 && !IS_ERR(object##_led.class_dev)) \
1072 led_classdev_unregister(&object##_led)
1073 1071
1074static void asus_led_exit(void) 1072static void asus_led_exit(void)
1075{ 1073{
1074 destroy_workqueue(led_workqueue);
1076 ASUS_LED_UNREGISTER(mled); 1075 ASUS_LED_UNREGISTER(mled);
1077 ASUS_LED_UNREGISTER(tled); 1076 ASUS_LED_UNREGISTER(tled);
1078 ASUS_LED_UNREGISTER(pled); 1077 ASUS_LED_UNREGISTER(pled);
1079 ASUS_LED_UNREGISTER(rled); 1078 ASUS_LED_UNREGISTER(rled);
1080 ASUS_LED_UNREGISTER(gled); 1079 ASUS_LED_UNREGISTER(gled);
1081
1082 destroy_workqueue(led_workqueue);
1083} 1080}
1084 1081
1085static void __exit asus_laptop_exit(void) 1082static void __exit asus_laptop_exit(void)
@@ -1135,29 +1132,42 @@ static int asus_led_init(struct device *dev)
1135 1132
1136 rv = ASUS_LED_REGISTER(mled, dev); 1133 rv = ASUS_LED_REGISTER(mled, dev);
1137 if (rv) 1134 if (rv)
1138 return rv; 1135 goto out;
1139 1136
1140 rv = ASUS_LED_REGISTER(tled, dev); 1137 rv = ASUS_LED_REGISTER(tled, dev);
1141 if (rv) 1138 if (rv)
1142 return rv; 1139 goto out1;
1143 1140
1144 rv = ASUS_LED_REGISTER(rled, dev); 1141 rv = ASUS_LED_REGISTER(rled, dev);
1145 if (rv) 1142 if (rv)
1146 return rv; 1143 goto out2;
1147 1144
1148 rv = ASUS_LED_REGISTER(pled, dev); 1145 rv = ASUS_LED_REGISTER(pled, dev);
1149 if (rv) 1146 if (rv)
1150 return rv; 1147 goto out3;
1151 1148
1152 rv = ASUS_LED_REGISTER(gled, dev); 1149 rv = ASUS_LED_REGISTER(gled, dev);
1153 if (rv) 1150 if (rv)
1154 return rv; 1151 goto out4;
1155 1152
1156 led_workqueue = create_singlethread_workqueue("led_workqueue"); 1153 led_workqueue = create_singlethread_workqueue("led_workqueue");
1157 if (!led_workqueue) 1154 if (!led_workqueue)
1158 return -ENOMEM; 1155 goto out5;
1159 1156
1160 return 0; 1157 return 0;
1158out5:
1159 rv = -ENOMEM;
1160 ASUS_LED_UNREGISTER(gled);
1161out4:
1162 ASUS_LED_UNREGISTER(pled);
1163out3:
1164 ASUS_LED_UNREGISTER(rled);
1165out2:
1166 ASUS_LED_UNREGISTER(tled);
1167out1:
1168 ASUS_LED_UNREGISTER(mled);
1169out:
1170 return rv;
1161} 1171}
1162 1172
1163static int __init asus_laptop_init(void) 1173static int __init asus_laptop_init(void)