From patchwork Sun Aug 2 15:55:39 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Jenkins X-Patchwork-Id: 38764 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 n72FnJdk005313 for ; Sun, 2 Aug 2009 15:55:44 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752834AbZHBPzm (ORCPT ); Sun, 2 Aug 2009 11:55:42 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752840AbZHBPzm (ORCPT ); Sun, 2 Aug 2009 11:55:42 -0400 Received: from ey-out-2122.google.com ([74.125.78.24]:14002 "EHLO ey-out-2122.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752834AbZHBPzl (ORCPT ); Sun, 2 Aug 2009 11:55:41 -0400 Received: by ey-out-2122.google.com with SMTP id 9so821482eyd.37 for ; Sun, 02 Aug 2009 08:55:41 -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=2e89PIl8IfD1nI275KbESPpjVYf/ZGR9HS3tJbpMzek=; b=Z+USn/5Ht9iTxIAFtmpWbWZaJIJQ2KgK0/nRhKjwukpP7SGD6JBHsMZKpFcop3kDnL lwReSRTHWRaoKL9P+B8s1Idv1t1qg+Qp5bEd6W6xJ236E5WdoXZW6M/xxmIOUB5yXQqx HsPzPwMAQzHExtDnfgQ/ZGENcr8+sSxZGAVTg= 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=geoti1xOpwcJfQ0LNLxURWZ2pBxy+useQqX7Azgq2t/BwOsK/jifL0Zns8tLDfUtY2 oAck8/1mbbqW81HIis4IAX8pspuc+LlIz8L/5Mt8zmfskzfQ1fDD5cHJ0yX28RZCOaes GluCngzArtmqAtTpI7S13pw9V96VSrYPab604= Received: by 10.210.136.15 with SMTP id j15mr3821416ebd.21.1249228541424; Sun, 02 Aug 2009 08:55:41 -0700 (PDT) Received: from ?192.168.0.2? ([86.53.68.233]) by mx.google.com with ESMTPS id 5sm9574555eyh.56.2009.08.02.08.55.40 (version=SSLv3 cipher=RC4-MD5); Sun, 02 Aug 2009 08:55:41 -0700 (PDT) Message-ID: <4A75B6FB.8030503@tuffmail.co.uk> Date: Sun, 02 Aug 2009 16:55:39 +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 2/8] eeepc-laptop: fix pci hotplug race on load and unload Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Wifi rfkill state changes can race with pci hotplug cleanup. A simple fix is to refresh the hotplug state just before deregistering the pci hotplug slot. There is also potential for a hotplug notification to fire too early during setup, while the structures it uses are still being initialised. (This could only happen if the BIOS performs hotplug itself; a bug triggered by removing the battery while hibernated). Avoid this by registering the notifier later. The same refresh mechanism is used to handle rfkill state changes which can now race with registration. Signed-off-by: Alan Jenkins --- drivers/platform/x86/eeepc-laptop.c | 77 ++++++++++++++++++++-------------- 1 files changed, 45 insertions(+), 32 deletions(-) diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 1790103..8dd86f7 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -667,37 +667,37 @@ static void eeepc_rfkill_hotplug(void) struct pci_bus *bus; bool blocked = eeepc_wlan_rfkill_blocked(); - rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); + if (ehotk->wlan_rfkill) + rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); mutex_lock(&ehotk->hotplug_lock); - if (ehotk->hotplug_slot == NULL) - goto out_unlock; - - bus = pci_find_bus(0, 1); - if (!bus) { - pr_warning("Unable to find PCI bus 1?\n"); - goto out_unlock; - } - - if (!blocked) { - dev = pci_get_slot(bus, 0); - if (dev) { - /* Device already present */ - pci_dev_put(dev); + if (ehotk->hotplug_slot) { + bus = pci_find_bus(0, 1); + if (!bus) { + pr_warning("Unable to find PCI bus 1?\n"); goto out_unlock; } - dev = pci_scan_single_device(bus, 0); - if (dev) { - pci_bus_assign_resources(bus); - if (pci_bus_add_device(dev)) - pr_err("Unable to hotplug wifi\n"); - } - } else { - dev = pci_get_slot(bus, 0); - if (dev) { - pci_remove_bus_device(dev); - pci_dev_put(dev); + + if (!blocked) { + dev = pci_get_slot(bus, 0); + if (dev) { + /* Device already present */ + pci_dev_put(dev); + goto out_unlock; + } + dev = pci_scan_single_device(bus, 0); + if (dev) { + pci_bus_assign_resources(bus); + if (pci_bus_add_device(dev)) + pr_err("Unable to hotplug wifi\n"); + } + } else { + dev = pci_get_slot(bus, 0); + if (dev) { + pci_remove_bus_device(dev); + pci_dev_put(dev); + } } } @@ -1029,14 +1029,22 @@ static void eeepc_rfkill_exit(void) { eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); - if (ehotk->wlan_rfkill) + if (ehotk->wlan_rfkill) { rfkill_unregister(ehotk->wlan_rfkill); + ehotk->wlan_rfkill = NULL; + } + /* + * Refresh pci hotplug in case the rfkill state was changed after + * eeepc_unregister_rfkill_notifier() + */ + eeepc_rfkill_hotplug(); + if (ehotk->hotplug_slot) + pci_hp_deregister(ehotk->hotplug_slot); + if (ehotk->bluetooth_rfkill) rfkill_unregister(ehotk->bluetooth_rfkill); if (ehotk->wwan3g_rfkill) rfkill_unregister(ehotk->wwan3g_rfkill); - if (ehotk->hotplug_slot) - pci_hp_deregister(ehotk->hotplug_slot); } static void eeepc_input_exit(void) @@ -1104,9 +1112,6 @@ static int eeepc_rfkill_init(struct device *dev) mutex_init(&ehotk->hotplug_lock); - eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); - eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); - result = eeepc_new_rfkill(&ehotk->wlan_rfkill, "eeepc-wlan", dev, RFKILL_TYPE_WLAN, CM_ASL_WLAN); @@ -1136,6 +1141,14 @@ static int eeepc_rfkill_init(struct device *dev) if (result == -EBUSY) result = 0; + eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); + eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); + /* + * Refresh pci hotplug in case the rfkill state was changed during + * setup. + */ + eeepc_rfkill_hotplug(); + exit: if (result && result != -ENODEV) eeepc_rfkill_exit();