From patchwork Tue Mar 28 10:01:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 667931 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 555E4C761A6 for ; Tue, 28 Mar 2023 10:03:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230047AbjC1KCh (ORCPT ); Tue, 28 Mar 2023 06:02:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52994 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232701AbjC1KCL (ORCPT ); Tue, 28 Mar 2023 06:02:11 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9F48B6A4E; Tue, 28 Mar 2023 03:02:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1679997729; x=1711533729; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=013xeHnW9lttA/KQdmfxgHU0jNti/+KDIk0yVRBwKSQ=; b=aImN0zA1BU3dYio8rOQ2YxwdYzmIeF130SdpYSznYXwHhGP3x4RHqxYW TsA4OZZhYOPdCRcJLVZW++MS4wot3YptX70T5TZyDKv1g1o9bs8UJiXZ8 qfYS707RgJrPxByHX8rpZ5eCeqrrQt2F3nuM8UO9546Y7jQV8zd3U54yt Qd9OnfW5zNWILEVXDa0t+dCnd3L2eAAsKs6jwTM8EDwlrM5kUjRHW0yYt 0AZ4r77xY4qO/RZ2Wl1R/2xqjoPtmlE7LNFcDwpMHKrW6XtDiVeu2P65y SlYtAAK66R6Gf/Fw8uIt/M3BZaKOaxLC4apfkbJGAtGDEOHkDyGIC65dV Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10662"; a="324419979" X-IronPort-AV: E=Sophos;i="5.98,297,1673942400"; d="scan'208";a="324419979" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2023 03:02:06 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10662"; a="753078499" X-IronPort-AV: E=Sophos;i="5.98,297,1673942400"; d="scan'208";a="753078499" Received: from turnipsi.fi.intel.com (HELO kekkonen.fi.intel.com) ([10.237.72.44]) by fmsmga004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Mar 2023 03:02:03 -0700 Received: from svinhufvud.ger.corp.intel.com (localhost [IPv6:::1]) by kekkonen.fi.intel.com (Postfix) with ESMTP id 1BC3112243C; Tue, 28 Mar 2023 13:02:01 +0300 (EEST) From: Sakari Ailus To: linux-acpi@vger.kernel.org Cc: linux-media@vger.kernel.org, rafael@kernel.org, andriy.shevchenko@linux.intel.com, heikki.krogerus@linux.intel.com Subject: [PATCH v6 01/10] ACPI: scan: Remove the second DSDT traversal Date: Tue, 28 Mar 2023 13:01:49 +0300 Message-Id: <20230328100159.1457160-2-sakari.ailus@linux.intel.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230328100159.1457160-1-sakari.ailus@linux.intel.com> References: <20230328100159.1457160-1-sakari.ailus@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Collect the devices with _DEP into a list and continue processing them after a full traversal, instead of doing a full second traversal of the tree. This makes the second DSDT traversal pass unnecessary as we already have the nodes we're interested in in a linked list. Signed-off-by: Sakari Ailus --- drivers/acpi/scan.c | 125 ++++++++++++++++++++++++++++++++------------ 1 file changed, 92 insertions(+), 33 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 0c6f06abe3f4..df97c2babf39 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -2029,10 +2029,52 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep) return count; } -static bool acpi_bus_scan_second_pass; +/** + * struct acpi_postponed_handle - A postponed ACPI handle + * @handle: The postponed handle + * @list: Entry in a postponed list + * + * One such entry represents an ACPI handle the scanning of which has been + * postponed. + */ +struct acpi_postponed_handle { + acpi_handle handle; + struct list_head list; +}; + +/** + * struct acpi_scan_context - Context for scanning ACPI devices + * @device: The first encountered device, typically the root of the scanned tree + * @postponed_head: The list head of the postponed ACPI handles + */ +struct acpi_scan_context { + struct acpi_device *device; + struct list_head postponed_head; +}; + +/** + * acpi_bus_handle_postpone - Add an ACPI handle to a given postponed list + * @handle: The ACPI handle + * @head: Postponed list head + * + * Add a given ACPI handle to a list of ACPI objects for which the creation + * of the device objects is to be postponed. + */ +static void acpi_bus_handle_postpone(acpi_handle handle, + struct list_head *head) +{ + struct acpi_postponed_handle *ph; + + ph = kzalloc(sizeof(*ph), GFP_KERNEL); + if (!ph) + return; + + ph->handle = handle; + list_add(&ph->list, head); +} static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep, - struct acpi_device **adev_p) + struct acpi_scan_context *ctx) { struct acpi_device *device = acpi_fetch_acpi_dev(handle); acpi_object_type acpi_type; @@ -2051,7 +2093,7 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep, /* Bail out if there are dependencies. */ if (acpi_scan_check_dep(handle, check_dep) > 0) { - acpi_bus_scan_second_pass = true; + acpi_bus_handle_postpone(handle, &ctx->postponed_head); return AE_CTRL_DEPTH; } @@ -2086,22 +2128,22 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep, acpi_scan_init_hotplug(device); out: - if (!*adev_p) - *adev_p = device; + if (!ctx->device) + ctx->device = device; return AE_OK; } static acpi_status acpi_bus_check_add_1(acpi_handle handle, u32 lvl_not_used, - void *not_used, void **ret_p) + void *ctx, void **unused) { - return acpi_bus_check_add(handle, true, (struct acpi_device **)ret_p); + return acpi_bus_check_add(handle, true, (struct acpi_scan_context *)ctx); } static acpi_status acpi_bus_check_add_2(acpi_handle handle, u32 lvl_not_used, - void *not_used, void **ret_p) + void *ctx, void **device) { - return acpi_bus_check_add(handle, false, (struct acpi_device **)ret_p); + return acpi_bus_check_add(handle, false, (struct acpi_scan_context *)ctx); } static void acpi_default_enumeration(struct acpi_device *device) @@ -2422,37 +2464,54 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_next_consumer_dev); */ int acpi_bus_scan(acpi_handle handle) { - struct acpi_device *device = NULL; - - acpi_bus_scan_second_pass = false; - - /* Pass 1: Avoid enumerating devices with missing dependencies. */ + struct acpi_scan_context ctx = { + .postponed_head = LIST_HEAD_INIT(ctx.postponed_head), + }; + struct acpi_postponed_handle *ph, *tmp_ph; + int ret = 0; - if (ACPI_SUCCESS(acpi_bus_check_add(handle, true, &device))) + if (ACPI_SUCCESS(acpi_bus_check_add(handle, true, &ctx))) acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add_1, NULL, NULL, - (void **)&device); - - if (!device) - return -ENODEV; - - acpi_bus_attach(device, (void *)true); + acpi_bus_check_add_1, NULL, (void *)&ctx, + NULL); - if (!acpi_bus_scan_second_pass) - return 0; - - /* Pass 2: Enumerate all of the remaining devices. */ + if (!ctx.device) { + ret = -ENODEV; + goto out_release; + } - device = NULL; + acpi_bus_attach(ctx.device, (void *)true); - if (ACPI_SUCCESS(acpi_bus_check_add(handle, false, &device))) - acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - acpi_bus_check_add_2, NULL, NULL, - (void **)&device); + /* + * Proceed to register ACPI devices that were postponed due to _DEP + * objects during the namespace walk. + */ + list_for_each_entry_safe(ph, tmp_ph, &ctx.postponed_head, list) { + list_del(&ph->list); + /* Set device NULL here to obtain the root for this sub-tree. */ + ctx.device = NULL; + /* + * Do this manually, as the namespace walk will only include + * sub-nodes, not the node itself. ctx.device is set to the + * ACPI device corresponding ph->handle. + */ + acpi_bus_check_add_2(ph->handle, 0, &ctx, NULL); + /* Walk the rest of the sub-namespace. */ + acpi_walk_namespace(ACPI_TYPE_ANY, ph->handle, ACPI_UINT32_MAX, + acpi_bus_check_add_2, NULL, (void *)&ctx, + NULL); + if (ctx.device) + acpi_bus_attach(ctx.device, NULL); + kfree(ph); + } - acpi_bus_attach(device, NULL); +out_release: + list_for_each_entry_safe(ph, tmp_ph, &ctx.postponed_head, list) { + list_del(&ph->list); + kfree(ph); + } - return 0; + return ret; } EXPORT_SYMBOL(acpi_bus_scan);