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=-19.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, 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=unavailable 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 96CD3C43333 for ; Fri, 5 Feb 2021 22:26:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 50D1064E0D for ; Fri, 5 Feb 2021 22:26:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233233AbhBEW0L (ORCPT ); Fri, 5 Feb 2021 17:26:11 -0500 Received: from mail.kernel.org ([198.145.29.99]:44980 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232851AbhBEOyw (ORCPT ); Fri, 5 Feb 2021 09:54:52 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 95D9D650C4; Fri, 5 Feb 2021 14:14:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1612534496; bh=caA55sIiCpe1X+tGnqPjpicNBT/1vVp/DxEmiop0XtE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GkrHs5ceAC15QzSCbudufptkPSzQUCh3Ybf7cEYt8r7dZCFYEMmz0v5u6p37HYbdR xYW0OWLSUakrigvLiRl4QE7AuzPkcTlOf6G3HrDn9QMeHKUqV7qy5ISyLStLn+lTuK gw4K2VdMmq7tjhSTBFmlmdSkcsiUL+WwyVcVR5dQ= 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" , Sudip Mukherjee Subject: [PATCH 4.14 07/15] driver core: Extend device_is_dependent() Date: Fri, 5 Feb 2021 15:08:52 +0100 Message-Id: <20210205140650.022247260@linuxfoundation.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210205140649.733510103@linuxfoundation.org> References: <20210205140649.733510103@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: linux-kernel@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 Signed-off-by: Sudip Mukherjee 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 @@ -96,6 +96,16 @@ void device_links_read_unlock(int not_us } #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. @@ -109,7 +119,12 @@ static int device_is_dependent(struct de 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);