From patchwork Sat May 27 05:31:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Darren Hart X-Patchwork-Id: 9751561 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 57B7B6032C for ; Sat, 27 May 2017 05:35:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4A4E3283C5 for ; Sat, 27 May 2017 05:35:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3F4682846A; Sat, 27 May 2017 05:35:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D6A79283C5 for ; Sat, 27 May 2017 05:35:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752217AbdE0FcK (ORCPT ); Sat, 27 May 2017 01:32:10 -0400 Received: from bombadil.infradead.org ([65.50.211.133]:45030 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752120AbdE0Fbw (ORCPT ); Sat, 27 May 2017 01:31:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=Content-Transfer-Encoding: Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=KRxbskF9U0kXNdXahSRtk0RGZqdbmDNk/10K6CHUjBc=; b=Dk0iBoTKwy3swB7eAaRJNYkL9 VASRJDGh9GnfIvCFhhkPkZUrh9kKn8Ypa9ng1rbYEWCd4k2XDyeOn7UGKNcMXzH278pLMfwoA4HbU Wp8YoBG7Utxtdrwu7qodevKqQXyVXqygDVdAbTJ1Zt555ArvCS+yN8YzJnOkaEdLkuMwTRJqkMcs2 o2ZNs4TZWBIUVMKYWYuQaCmCFKcd8u6wjQgx2a4eJMxItwgEF/Sb52jAZ+WjimrgVwyVfWu2kFzfc kPaTaLyU9aAUsgDj4vDYwonMI4qt9p0bXCMQE51Mh1HpZ3O4A7aZDXMRw8VUFnC43eBYGpq0ht7v1 Fc8AX/1zQ==; Received: from dvhart by bombadil.infradead.org with local (Exim 4.87 #1 (Red Hat Linux)) id 1dEUKN-0000hk-GS; Sat, 27 May 2017 05:31:51 +0000 From: Darren Hart To: platform-driver-x86@vger.kernel.org Cc: Andy Shevchenko , Andy Lutomirski , Andy Lutomirski , Mario Limonciello , =?UTF-8?q?Pali=20Roh=C3=A1r?= , Rafael Wysocki , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, Darren Hart Subject: [PATCH 09/16] platform/x86: wmi: Instantiate all devices before adding them Date: Fri, 26 May 2017 22:31:23 -0700 Message-Id: X-Mailer: git-send-email 2.9.4 In-Reply-To: References: In-Reply-To: References: MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Andy Lutomirski At some point, we will want sub-drivers to get references to other devices on the same WMI bus. This change is needed to avoid races. This ends up simplifying the setup code and fixing some leaks, too. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Mario Limonciello Cc: Pali Rohár Cc: Rafael Wysocki Cc: linux-kernel@vger.kernel.org Cc: platform-driver-x86@vger.kernel.org Cc: linux-acpi@vger.kernel.org Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/wmi.c | 49 +++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 651693a..bfc0a3f 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -796,7 +796,7 @@ static struct device_type wmi_type_data = { .release = wmi_dev_release, }; -static int wmi_create_device(struct device *wmi_bus_dev, +static void wmi_create_device(struct device *wmi_bus_dev, const struct guid_block *gblock, struct wmi_block *wblock, struct acpi_device *device) @@ -852,7 +852,7 @@ static int wmi_create_device(struct device *wmi_bus_dev, } - return device_register(&wblock->dev.dev); + device_initialize(&wblock->dev.dev); } static void wmi_free_devices(struct acpi_device *device) @@ -863,10 +863,14 @@ static void wmi_free_devices(struct acpi_device *device) list_for_each_entry_safe(wblock, next, &wmi_block_list, list) { if (wblock->acpi_device == device) { list_del(&wblock->list); - if (wblock->dev.dev.bus) - device_unregister(&wblock->dev.dev); - else + if (wblock->dev.dev.bus) { + /* Device was initialized. */ + device_del(&wblock->dev.dev); + put_device(&wblock->dev.dev); + } else { + /* device_initialize was not called. */ kfree(wblock); + } } } } @@ -901,9 +905,9 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device) struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *obj; const struct guid_block *gblock; - struct wmi_block *wblock; + struct wmi_block *wblock, *next; acpi_status status; - int retval; + int retval = 0; u32 i, total; status = acpi_evaluate_object(device->handle, "_WDG", NULL, &out); @@ -936,19 +940,15 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device) continue; wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); - if (!wblock) - return -ENOMEM; + if (!wblock) { + retval = -ENOMEM; + break; + } wblock->acpi_device = device; wblock->gblock = gblock[i]; - retval = wmi_create_device(wmi_bus_dev, &gblock[i], - wblock, device); - if (retval) { - put_device(&wblock->dev.dev); - wmi_free_devices(device); - goto out_free_pointer; - } + wmi_create_device(wmi_bus_dev, &gblock[i], wblock, device); list_add_tail(&wblock->list, &wmi_block_list); @@ -958,11 +958,24 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device) } } - retval = 0; - out_free_pointer: kfree(out.pointer); + /* + * Now that all of the devices are created, add them to the + * device tree and probe subdrivers. + */ + list_for_each_entry_safe(wblock, next, &wmi_block_list, list) { + if (wblock->acpi_device == device) { + if (device_add(&wblock->dev.dev) != 0) { + dev_err(wmi_bus_dev, + "failed to register %pULL\n", + wblock->gblock.guid); + list_del(&wblock->list); + } + } + } + return retval; }