aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorAlan Jenkins <alan-jenkins@tuffmail.co.uk>2009-08-28 08:56:35 -0400
committerLen Brown <len.brown@intel.com>2009-08-28 15:21:11 -0400
commit1e7798547fe6920ae27fb92c9202353e9e4c55db (patch)
tree0e8672632daf6501eb879e4772ef44ddd1ef2162 /drivers/platform
parent07e84aa98f6b3a7278d3267f6f657955ed3eb973 (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.c120
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
850static 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
879static 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
888static int eeepc_hotk_resume(struct acpi_device *device) 850static 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
1069static 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
1082static int eeepc_new_rfkill(struct rfkill **rfkill, 1031static 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
1196static int __init eeepc_laptop_init(void) 1145static 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
1249fail_rfkill: 1205fail_rfkill:
1250 eeepc_hwmon_exit(); 1206 eeepc_hwmon_exit();
1251fail_hwmon: 1207fail_hwmon:
@@ -1261,8 +1217,50 @@ fail_platform_device1:
1261 platform_driver_unregister(&platform_driver); 1217 platform_driver_unregister(&platform_driver);
1262fail_platform_driver: 1218fail_platform_driver:
1263 eeepc_input_exit(); 1219 eeepc_input_exit();
1220fail_check:
1221 kfree(ehotk);
1222
1264 return result; 1223 return result;
1265} 1224}
1266 1225
1226static 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
1244static 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
1260static void __exit eeepc_laptop_exit(void)
1261{
1262 acpi_bus_unregister_driver(&eeepc_hotk_driver);
1263}
1264
1267module_init(eeepc_laptop_init); 1265module_init(eeepc_laptop_init);
1268module_exit(eeepc_laptop_exit); 1266module_exit(eeepc_laptop_exit);