From patchwork Sun Aug 2 15:56:12 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Jenkins X-Patchwork-Id: 38765 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n72FnJdm005313 for ; Sun, 2 Aug 2009 15:56:17 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752840AbZHBP4P (ORCPT ); Sun, 2 Aug 2009 11:56:15 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752862AbZHBP4P (ORCPT ); Sun, 2 Aug 2009 11:56:15 -0400 Received: from mail-ew0-f214.google.com ([209.85.219.214]:35842 "EHLO mail-ew0-f214.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752840AbZHBP4O (ORCPT ); Sun, 2 Aug 2009 11:56:14 -0400 Received: by ewy10 with SMTP id 10so2535576ewy.37 for ; Sun, 02 Aug 2009 08:56:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:received:received:sender:message-id:date:from :user-agent:mime-version:to:cc:subject:content-type :content-transfer-encoding; bh=G78FDT/zLg0NYl79IYFvYdoPGfOMK1bDbs6yIvIH/OU=; b=R8rVGuwTVHWnXlWbv62FWDBv1AiCGBKJ8ISxBIbv1HGf3qsWZEEIWQXZtAYa4tZhfy lPdUlNdabi7KhW1DVo0gMyVTc9W9zo7WAODzGScVr/VA1/1il4RcWszg+EXsMjOjXZx/ pxUa4QMW19b2xDF8Tq31sp438fZEzF/v50lls= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=sender:message-id:date:from:user-agent:mime-version:to:cc:subject :content-type:content-transfer-encoding; b=rnZYGC/Wyn0ZDMQr32DTOtqXGajDPf/CjrjH74AJHO4We/4O+0/6lhmuWfaq0ofVRj trmxrhYnztZdl3P+uqHcvBTlKBfh1/4mgL7XmJBL8fPubuPz2GqHB4P+ybJ7sODEz60+ XNWik9md4G9YrA7/Ra7ZdIqm1IMw8QfnqPQHM= Received: by 10.210.129.20 with SMTP id b20mr6032462ebd.78.1249228574329; Sun, 02 Aug 2009 08:56:14 -0700 (PDT) Received: from ?192.168.0.2? ([86.53.68.233]) by mx.google.com with ESMTPS id 28sm9064866eyg.20.2009.08.02.08.56.13 (version=SSLv3 cipher=RC4-MD5); Sun, 02 Aug 2009 08:56:14 -0700 (PDT) Message-ID: <4A75B71C.7030202@tuffmail.co.uk> Date: Sun, 02 Aug 2009 16:56:12 +0100 From: Alan Jenkins User-Agent: Thunderbird 2.0.0.21 (X11/20090318) MIME-Version: 1.0 To: Corentin Chary CC: acpi4asus-user@lists.sourceforge.net, linux-acpi@vger.kernel.org Subject: [PATCH 3/8] eeepc-laptop: fix ordering of init and exit functions Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org 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 --- 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 8dd86f7..cf47d1c 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -847,44 +847,6 @@ error_slot: return ret; } -static int eeepc_hotk_add(struct acpi_device *device) -{ - int result; - - if (!device) - return -EINVAL; - pr_notice(EEEPC_HOTK_NAME "\n"); - ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); - if (!ehotk) - return -ENOMEM; - ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH; - ehotk->handle = device->handle; - strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); - strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); - device->driver_data = ehotk; - ehotk->device = device; - result = eeepc_hotk_check(); - if (result) - goto ehotk_fail; - - return 0; - - ehotk_fail: - kfree(ehotk); - ehotk = NULL; - - return result; -} - -static int eeepc_hotk_remove(struct acpi_device *device, int type) -{ - if (!device || !acpi_driver_data(device)) - return -EINVAL; - - kfree(ehotk); - return 0; -} - static int eeepc_hotk_resume(struct acpi_device *device) { if (ehotk->wlan_rfkill) { @@ -1066,19 +1028,6 @@ static void eeepc_hwmon_exit(void) eeepc_hwmon_device = NULL; } -static void __exit eeepc_laptop_exit(void) -{ - eeepc_backlight_exit(); - eeepc_rfkill_exit(); - eeepc_input_exit(); - eeepc_hwmon_exit(); - acpi_bus_unregister_driver(&eeepc_hotk_driver); - sysfs_remove_group(&platform_device->dev.kobj, - &platform_attribute_group); - platform_device_unregister(platform_device); - platform_driver_unregister(&platform_driver); -} - static int eeepc_new_rfkill(struct rfkill **rfkill, const char *name, struct device *dev, enum rfkill_type type, int cm) @@ -1193,21 +1142,27 @@ static int eeepc_hwmon_init(struct device *dev) return result; } -static int __init eeepc_laptop_init(void) +static int eeepc_hotk_add(struct acpi_device *device) { struct device *dev; int result; - if (acpi_disabled) - return -ENODEV; - result = acpi_bus_register_driver(&eeepc_hotk_driver); - if (result < 0) - return result; - if (!ehotk) { - acpi_bus_unregister_driver(&eeepc_hotk_driver); - return -ENODEV; - } + if (!device) + return -EINVAL; + pr_notice(EEEPC_HOTK_NAME "\n"); + ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); + if (!ehotk) + return -ENOMEM; + ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH; + ehotk->handle = device->handle; + strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); + strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); + device->driver_data = ehotk; + ehotk->device = device; + result = eeepc_hotk_check(); + if (result) + goto fail_check; eeepc_enable_camera(); /* Register platform stuff */ @@ -1246,6 +1201,7 @@ static int __init eeepc_laptop_init(void) goto fail_rfkill; return 0; + fail_rfkill: eeepc_hwmon_exit(); fail_hwmon: @@ -1261,8 +1217,50 @@ fail_platform_device1: platform_driver_unregister(&platform_driver); fail_platform_driver: eeepc_input_exit(); +fail_check: + kfree(ehotk); + return result; } +static int eeepc_hotk_remove(struct acpi_device *device, int type) +{ + if (!device || !acpi_driver_data(device)) + return -EINVAL; + + eeepc_backlight_exit(); + eeepc_rfkill_exit(); + eeepc_input_exit(); + eeepc_hwmon_exit(); + sysfs_remove_group(&platform_device->dev.kobj, + &platform_attribute_group); + platform_device_unregister(platform_device); + platform_driver_unregister(&platform_driver); + + kfree(ehotk); + return 0; +} + +static int __init eeepc_laptop_init(void) +{ + int result; + + if (acpi_disabled) + return -ENODEV; + result = acpi_bus_register_driver(&eeepc_hotk_driver); + if (result < 0) + return result; + if (!ehotk) { + acpi_bus_unregister_driver(&eeepc_hotk_driver); + return -ENODEV; + } + return 0; +} + +static void __exit eeepc_laptop_exit(void) +{ + acpi_bus_unregister_driver(&eeepc_hotk_driver); +} + module_init(eeepc_laptop_init); module_exit(eeepc_laptop_exit);