From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D1BDCC433E0 for ; Tue, 26 Jan 2021 05:06:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8B4AF22B3B for ; Tue, 26 Jan 2021 05:06:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730841AbhAZFEh (ORCPT ); Tue, 26 Jan 2021 00:04:37 -0500 Received: from mail.kernel.org ([198.145.29.99]:39556 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726524AbhAYSxN (ORCPT ); Mon, 25 Jan 2021 13:53:13 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 86C2E22DFB; Mon, 25 Jan 2021 18:52:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1611600770; bh=6kIEcAspjmU3aXjIX8YIBhv2FZDRttQUkJFimwmZTP0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N0w2pglv1SISgDy1A7ycu8KWsGXNntV6mslrtwNKOUhcSL1C0N28rPX7OEIJJw3dR P0g4dZvTX58Y/3iK0B9obWpuUIu35sGPIoz05R6RSM0nOqCAP5Ga2CR4TqDYQl1acm zHmI5Jfzv23JdKyXIe1ZJeZ/WaxHE9B0cC1vKI1g= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Stephan Gerhold , Saravana Kannan , "Rafael J. Wysocki" Subject: [PATCH 5.10 144/199] driver core: Extend device_is_dependent() Date: Mon, 25 Jan 2021 19:39:26 +0100 Message-Id: <20210125183222.292048911@linuxfoundation.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210125183216.245315437@linuxfoundation.org> References: <20210125183216.245315437@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Rafael J. Wysocki commit 3d1cf435e201d1fd63e4346b141881aed086effd upstream. If the device passed as the target (second argument) to device_is_dependent() is not completely registered (that is, it has been initialized, but not added yet), but the parent pointer of it is set, it may be missing from the list of the parent's children and device_for_each_child() called by device_is_dependent() cannot be relied on to catch that dependency. For this reason, modify device_is_dependent() to check the ancestors of the target device by following its parent pointer in addition to the device_for_each_child() walk. Fixes: 9ed9895370ae ("driver core: Functional dependencies tracking support") Reported-by: Stephan Gerhold Tested-by: Stephan Gerhold Reviewed-by: Saravana Kannan Signed-off-by: Rafael J. Wysocki Link: https://lore.kernel.org/r/17705994.d592GUb2YH@kreacher Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -115,6 +115,16 @@ int device_links_read_lock_held(void) #endif #endif /* !CONFIG_SRCU */ +static bool device_is_ancestor(struct device *dev, struct device *target) +{ + while (target->parent) { + target = target->parent; + if (dev == target) + return true; + } + return false; +} + /** * device_is_dependent - Check if one device depends on another one * @dev: Device to check dependencies for. @@ -128,7 +138,12 @@ int device_is_dependent(struct device *d struct device_link *link; int ret; - if (dev == target) + /* + * The "ancestors" check is needed to catch the case when the target + * device has not been completely initialized yet and it is still + * missing from the list of children of its parent device. + */ + if (dev == target || device_is_ancestor(dev, target)) return 1; ret = device_for_each_child(dev, target, device_is_dependent);