diff options
author | Alan Jenkins <alan-jenkins@tuffmail.co.uk> | 2009-08-28 08:56:35 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-08-28 15:21:11 -0400 |
commit | 1e7798547fe6920ae27fb92c9202353e9e4c55db (patch) | |
tree | 0e8672632daf6501eb879e4772ef44ddd1ef2162 /drivers/platform | |
parent | 07e84aa98f6b3a7278d3267f6f657955ed3eb973 (diff) |
eeepc-laptop: fix ordering of init and exit functions
1. input and backlight devices were registered after acpi notifications
are enabled. This left a window where eeepc_hotk_notify() might
find these devices in an inconsistent (half-initialized) state.
-> Move all device registration into eeepc_hotk_add(), which is called
before enabling acpi notifications.
2. input and backlight devices were unregistered before acpi
notifications are disabled. This left a window where
eeepc_hotk_notify() might find these devices in an inconsistent
(half-destroyed) state.
-> Move all device unregistration into eeepc_hotk_remove(), which is
called after disabling acpi notifications.
3. The acpi driver was not freed if an error occured further down in
eeepc_laptop_init().
-> The rest of eeepc_laptop_init() has been moved to eeepc_hotk_add(),
so this is no longer a problem.
4. The acpi driver was unregistered before the platform driver. This
left a window where a sysfs access could attempt to read the ehotk
structure after it had been freed by eeepc_hotk_remove().
-> The acpi driver is now unregistered as the last step in
eeepc_laptop_exit(), so this is no longer a problem.
Signed-off-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 120 |
1 files changed, 59 insertions, 61 deletions
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 8dd86f73b844..cf47d1cd1a34 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
@@ -847,44 +847,6 @@ error_slot: | |||
847 | return ret; | 847 | return ret; |
848 | } | 848 | } |
849 | 849 | ||
850 | static int eeepc_hotk_add(struct acpi_device *device) | ||
851 | { | ||
852 | int result; | ||
853 | |||
854 | if (!device) | ||
855 | return -EINVAL; | ||
856 | pr_notice(EEEPC_HOTK_NAME "\n"); | ||
857 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); | ||
858 | if (!ehotk) | ||
859 | return -ENOMEM; | ||
860 | ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH; | ||
861 | ehotk->handle = device->handle; | ||
862 | strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); | ||
863 | strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); | ||
864 | device->driver_data = ehotk; | ||
865 | ehotk->device = device; | ||
866 | result = eeepc_hotk_check(); | ||
867 | if (result) | ||
868 | goto ehotk_fail; | ||
869 | |||
870 | return 0; | ||
871 | |||
872 | ehotk_fail: | ||
873 | kfree(ehotk); | ||
874 | ehotk = NULL; | ||
875 | |||
876 | return result; | ||
877 | } | ||
878 | |||
879 | static int eeepc_hotk_remove(struct acpi_device *device, int type) | ||
880 | { | ||
881 | if (!device || !acpi_driver_data(device)) | ||
882 | return -EINVAL; | ||
883 | |||
884 | kfree(ehotk); | ||
885 | return 0; | ||
886 | } | ||
887 | |||
888 | static int eeepc_hotk_resume(struct acpi_device *device) | 850 | static int eeepc_hotk_resume(struct acpi_device *device) |
889 | { | 851 | { |
890 | if (ehotk->wlan_rfkill) { | 852 | if (ehotk->wlan_rfkill) { |
@@ -1066,19 +1028,6 @@ static void eeepc_hwmon_exit(void) | |||
1066 | eeepc_hwmon_device = NULL; | 1028 | eeepc_hwmon_device = NULL; |
1067 | } | 1029 | } |
1068 | 1030 | ||
1069 | static void __exit eeepc_laptop_exit(void) | ||
1070 | { | ||
1071 | eeepc_backlight_exit(); | ||
1072 | eeepc_rfkill_exit(); | ||
1073 | eeepc_input_exit(); | ||
1074 | eeepc_hwmon_exit(); | ||
1075 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
1076 | sysfs_remove_group(&platform_device->dev.kobj, | ||
1077 | &platform_attribute_group); | ||
1078 | platform_device_unregister(platform_device); | ||
1079 | platform_driver_unregister(&platform_driver); | ||
1080 | } | ||
1081 | |||
1082 | static int eeepc_new_rfkill(struct rfkill **rfkill, | 1031 | static int eeepc_new_rfkill(struct rfkill **rfkill, |
1083 | const char *name, struct device *dev, | 1032 | const char *name, struct device *dev, |
1084 | enum rfkill_type type, int cm) | 1033 | enum rfkill_type type, int cm) |
@@ -1193,21 +1142,27 @@ static int eeepc_hwmon_init(struct device *dev) | |||
1193 | return result; | 1142 | return result; |
1194 | } | 1143 | } |
1195 | 1144 | ||
1196 | static int __init eeepc_laptop_init(void) | 1145 | static int eeepc_hotk_add(struct acpi_device *device) |
1197 | { | 1146 | { |
1198 | struct device *dev; | 1147 | struct device *dev; |
1199 | int result; | 1148 | int result; |
1200 | 1149 | ||
1201 | if (acpi_disabled) | 1150 | if (!device) |
1202 | return -ENODEV; | 1151 | return -EINVAL; |
1203 | result = acpi_bus_register_driver(&eeepc_hotk_driver); | 1152 | pr_notice(EEEPC_HOTK_NAME "\n"); |
1204 | if (result < 0) | 1153 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); |
1205 | return result; | 1154 | if (!ehotk) |
1206 | if (!ehotk) { | 1155 | return -ENOMEM; |
1207 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | 1156 | ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH; |
1208 | return -ENODEV; | 1157 | ehotk->handle = device->handle; |
1209 | } | 1158 | strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); |
1159 | strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); | ||
1160 | device->driver_data = ehotk; | ||
1161 | ehotk->device = device; | ||
1210 | 1162 | ||
1163 | result = eeepc_hotk_check(); | ||
1164 | if (result) | ||
1165 | goto fail_check; | ||
1211 | eeepc_enable_camera(); | 1166 | eeepc_enable_camera(); |
1212 | 1167 | ||
1213 | /* Register platform stuff */ | 1168 | /* Register platform stuff */ |
@@ -1246,6 +1201,7 @@ static int __init eeepc_laptop_init(void) | |||
1246 | goto fail_rfkill; | 1201 | goto fail_rfkill; |
1247 | 1202 | ||
1248 | return 0; | 1203 | return 0; |
1204 | |||
1249 | fail_rfkill: | 1205 | fail_rfkill: |
1250 | eeepc_hwmon_exit(); | 1206 | eeepc_hwmon_exit(); |
1251 | fail_hwmon: | 1207 | fail_hwmon: |
@@ -1261,8 +1217,50 @@ fail_platform_device1: | |||
1261 | platform_driver_unregister(&platform_driver); | 1217 | platform_driver_unregister(&platform_driver); |
1262 | fail_platform_driver: | 1218 | fail_platform_driver: |
1263 | eeepc_input_exit(); | 1219 | eeepc_input_exit(); |
1220 | fail_check: | ||
1221 | kfree(ehotk); | ||
1222 | |||
1264 | return result; | 1223 | return result; |
1265 | } | 1224 | } |
1266 | 1225 | ||
1226 | static int eeepc_hotk_remove(struct acpi_device *device, int type) | ||
1227 | { | ||
1228 | if (!device || !acpi_driver_data(device)) | ||
1229 | return -EINVAL; | ||
1230 | |||
1231 | eeepc_backlight_exit(); | ||
1232 | eeepc_rfkill_exit(); | ||
1233 | eeepc_input_exit(); | ||
1234 | eeepc_hwmon_exit(); | ||
1235 | sysfs_remove_group(&platform_device->dev.kobj, | ||
1236 | &platform_attribute_group); | ||
1237 | platform_device_unregister(platform_device); | ||
1238 | platform_driver_unregister(&platform_driver); | ||
1239 | |||
1240 | kfree(ehotk); | ||
1241 | return 0; | ||
1242 | } | ||
1243 | |||
1244 | static int __init eeepc_laptop_init(void) | ||
1245 | { | ||
1246 | int result; | ||
1247 | |||
1248 | if (acpi_disabled) | ||
1249 | return -ENODEV; | ||
1250 | result = acpi_bus_register_driver(&eeepc_hotk_driver); | ||
1251 | if (result < 0) | ||
1252 | return result; | ||
1253 | if (!ehotk) { | ||
1254 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
1255 | return -ENODEV; | ||
1256 | } | ||
1257 | return 0; | ||
1258 | } | ||
1259 | |||
1260 | static void __exit eeepc_laptop_exit(void) | ||
1261 | { | ||
1262 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
1263 | } | ||
1264 | |||
1267 | module_init(eeepc_laptop_init); | 1265 | module_init(eeepc_laptop_init); |
1268 | module_exit(eeepc_laptop_exit); | 1266 | module_exit(eeepc_laptop_exit); |