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); |
