From patchwork Tue Dec 1 01:05:59 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 7731561 Return-Path: X-Original-To: patchwork-linux-acpi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C76D29F387 for ; Tue, 1 Dec 2015 01:06:34 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E997F20641 for ; Tue, 1 Dec 2015 01:06:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 081252066B for ; Tue, 1 Dec 2015 01:06:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755343AbbLABGX (ORCPT ); Mon, 30 Nov 2015 20:06:23 -0500 Received: from mail.kernel.org ([198.145.29.136]:46818 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755107AbbLABGW (ORCPT ); Mon, 30 Nov 2015 20:06:22 -0500 Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 319A620673; Tue, 1 Dec 2015 01:06:21 +0000 (UTC) Received: from localhost (c-71-202-137-17.hsd1.ca.comcast.net [71.202.137.17]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 30C5A2066B; Tue, 1 Dec 2015 01:06:20 +0000 (UTC) From: Andy Lutomirski To: Darren Hart Cc: Matthew Garrett , linux-acpi@vger.kernel.org, platform-driver-x86@vger.kernel.org, Mario Limonciello , =?UTF-8?q?Pali=20Roh=C3=A1r?= , Andy Lutomirski Subject: [PATCH 09/14] wmi: Instantiate all devices before adding them Date: Mon, 30 Nov 2015 17:05:59 -0800 Message-Id: <344ad68ef32ea13d2a7bb81e3ced15c4507a6cc8.1448931782.git.luto@kernel.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: References: In-Reply-To: References: X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 At some point, we'll want to subdrivers 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 fixng some leaks, too. Signed-off-by: Andy Lutomirski --- 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 49be61207c4a..7d8a11a45bf9 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -869,7 +869,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) @@ -923,7 +923,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) @@ -934,10 +934,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); + } } } } @@ -972,9 +976,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); @@ -1007,19 +1011,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); @@ -1029,11 +1029,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; }