aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@ftp.linux.org.uk>2007-07-23 06:21:34 -0400
committerLen Brown <len.brown@intel.com>2007-07-23 13:35:23 -0400
commit3b0d71170d37878bbb1203ebc3f92e36d6151a80 (patch)
treef2371d2114c40f622a3f037df04d4e1684353171
parent3cc2649b879f0e83fd51b14c82bad5f8f208591e (diff)
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>
-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)