From patchwork Fri Jan 27 00:11:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Saravana Kannan X-Patchwork-Id: 13117981 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5B91FC05027 for ; Fri, 27 Jan 2023 00:15:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=mNvwCdCH0omZXsqTv6QPYKDp7lYl7mkqUmHNZ48PUI8=; b=N+GHdBZpWidPkuua5XpthN8Jd+ gOLtTjkd00uH/HbqZFnsvaoESzDOp4WzK5WfKrzBkYlgEu+xySx3eBtcBYdtx0TqY0f/vTEkpRQIu 0pzFKRdiQ7ITDxQQ/tWJHREnUXMI2gdF2FKsgpy4Y0W4Y9KhET/8mIpEcKV0Dh4w9rhSe+pXglzE7 BFtes6ocz1ddY2ifP5AMnUE5rMHKgoiCdR596I/BSRWIhTlWEaEmo4Fv3b7+0L0P4tORSXCaTT9kv FdkJHKFE2/Db0OgE9ZeOkCzauHt/Bjxz02kHu9OxbhinYmzAqfBYF7yNaqxF2UI8dKqvgsygIjOov 9TOA10UQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pLCNL-00CuyX-10; Fri, 27 Jan 2023 00:13:51 +0000 Received: from mail-yb1-xb4a.google.com ([2607:f8b0:4864:20::b4a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1pLCLW-00CuKG-Uu for linux-arm-kernel@lists.infradead.org; Fri, 27 Jan 2023 00:12:00 +0000 Received: by mail-yb1-xb4a.google.com with SMTP id z9-20020a25ba49000000b007d4416e3667so3668523ybj.23 for ; Thu, 26 Jan 2023 16:11:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=c3AwF4AtMHbX2LYsMliTqIx7wHDLzv0Hhup+BpQQIMM=; b=gTOp7490ea9U7jNjUY6xCQik8VP+9zqPskKVBpWRjts+bpGQ3P44rvtVPM2H5vWc5O g9xkHR8jX2pk1IXFr2K+taunlx1Lj3s05JSpST8DYMqd+QlQ8Zg3QwBCTf/q7VaeIcO9 tRDpOv24H9MY6zfGkQ9HozKTQvr8INcSsBSKLX3TWRiEOA5vyhyVx2m7bCk6h42PLl/M jenHPKvMJkZnYoOvwACSggMEWSHXAdeJ1f4GuF5OVOkq1YfH+Iou0UyIhKyCFubFaldD rpCkUDK3nZi0MSAESp/IiKwFKI7r3JZtmpkaS3JkaHCJ7qdacE+VksGzsn8zNzVR8Qrk E9Jg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:references:mime-version:message-id:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=c3AwF4AtMHbX2LYsMliTqIx7wHDLzv0Hhup+BpQQIMM=; b=KaWg94t7ic4gxIfGDrZblrlukVwuV6j80mgwk+g+kfO4IF+lJuGCWxOeHAxPfNsql/ dMbXdHaxk7PW5DvEvwsqeQGTAKLVj/1T/z+TRftIQdMU8tRWO2kj1pilyhCGgVG+/+Qp 5ZQBnY+oxNOmLGI0GWDx1H60r8ONAV/cbavHE44js25MVtfL/+xwTQAV8vR9u8eD6Nb5 rimgMLrx92xoXzAEcG8qAzD/eaf3yjldZhFCtsmjNcSIgwNA+fiquoGtfAZqYqct4t/X +cDUbFQrn5NO1nrjqpEa0WJn1par8hlFbicRcUSdG+5tC5BnwJRWiEbeZ9urJYGpgP12 eySQ== X-Gm-Message-State: AFqh2kpJV5TXfHS1hY6kH7eHvY9XoK5gh8cayoEoxqrlOcULScEomy2z cTXEdeWZOxVIO6qrzv03HFOnE16ZWpdza5o= X-Google-Smtp-Source: AMrXdXsndJMlXdYEau5sKjLp8uIAoWHu9UHhhqvmZmNLOTS0xxJ7nE4U4NJGHhPF8zOqeQxRce9UcSXfKT45dDI= X-Received: from saravanak.san.corp.google.com ([2620:15c:2d:3:c3b4:8b1c:e3ee:3708]) (user=saravanak job=sendgmr) by 2002:a81:b40b:0:b0:4fa:d728:aa1f with SMTP id h11-20020a81b40b000000b004fad728aa1fmr2633806ywi.349.1674778317519; Thu, 26 Jan 2023 16:11:57 -0800 (PST) Date: Thu, 26 Jan 2023 16:11:32 -0800 In-Reply-To: <20230127001141.407071-1-saravanak@google.com> Message-Id: <20230127001141.407071-6-saravanak@google.com> Mime-Version: 1.0 References: <20230127001141.407071-1-saravanak@google.com> X-Mailer: git-send-email 2.39.1.456.gfc5497dd1b-goog Subject: [PATCH v2 05/11] driver core: fw_devlink: Add DL_FLAG_CYCLE support to device links From: Saravana Kannan To: Greg Kroah-Hartman , "Rafael J. Wysocki" , Sudeep Holla , Cristian Marussi , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Marc Zyngier , Shawn Guo , Sascha Hauer , Pengutronix Kernel Team , Fabio Estevam , NXP Linux Team , Rob Herring , Frank Rowand , Geert Uytterhoeven , Magnus Damm , Len Brown , Andy Shevchenko , Daniel Scally , Heikki Krogerus , Sakari Ailus , Saravana Kannan Cc: Tony Lindgren , Linux Kernel Functional Testing , Naresh Kamboju , Abel Vesa , Alexander Stein , Geert Uytterhoeven , John Stultz , Doug Anderson , Guenter Roeck , Dmitry Baryshkov , Maxim Kiselev , Maxim Kochetkov , Miquel Raynal , Luca Weiss , Colin Foster , Martin Kepplinger , Jean-Philippe Brucker , kernel-team@android.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-renesas-soc@vger.kernel.org, linux-acpi@vger.kernel.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230126_161159_046704_79087C1D X-CRM114-Status: GOOD ( 22.13 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org fw_devlink uses DL_FLAG_SYNC_STATE_ONLY device link flag for two purposes: 1. To allow a parent device to proxy its child device's dependency on a supplier so that the supplier doesn't get its sync_state() callback before the child device/consumer can be added and probed. In this usage scenario, we need to ignore cycles for ensure correctness of sync_state() callbacks. 2. When there are dependency cycles in firmware, we don't know which of those dependencies are valid. So, we have to ignore them all wrt probe ordering while still making sure the sync_state() callbacks come correctly. However, when detecting dependency cycles, there can be multiple dependency cycles between two devices that we need to detect. For example: A -> B -> A and A -> C -> B -> A. To detect multiple cycles correct, we need to be able to differentiate DL_FLAG_SYNC_STATE_ONLY device links used for (1) vs (2) above. To allow this differentiation, add a DL_FLAG_CYCLE that can be use to mark use case (2). We can then use the DL_FLAG_CYCLE to decide which DL_FLAG_SYNC_STATE_ONLY device links to follow when looking for dependency cycles. Fixes: 2de9d8e0d2fe ("driver core: fw_devlink: Improve handling of cyclic dependencies") Signed-off-by: Saravana Kannan --- drivers/base/core.c | 28 ++++++++++++++++++---------- include/linux/device.h | 1 + 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 919728e784e8..e5390b09a02f 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -322,6 +322,12 @@ static bool device_is_ancestor(struct device *dev, struct device *target) return false; } +static inline bool device_link_flag_is_sync_state_only(u32 flags) +{ + return (flags & ~(DL_FLAG_INFERRED | DL_FLAG_CYCLE)) + == (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED); +} + /** * device_is_dependent - Check if one device depends on another one * @dev: Device to check dependencies for. @@ -348,8 +354,7 @@ int device_is_dependent(struct device *dev, void *target) return ret; list_for_each_entry(link, &dev->links.consumers, s_node) { - if ((link->flags & ~DL_FLAG_INFERRED) == - (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED)) + if (device_link_flag_is_sync_state_only(link->flags)) continue; if (link->consumer == target) @@ -422,8 +427,7 @@ static int device_reorder_to_tail(struct device *dev, void *not_used) device_for_each_child(dev, NULL, device_reorder_to_tail); list_for_each_entry(link, &dev->links.consumers, s_node) { - if ((link->flags & ~DL_FLAG_INFERRED) == - (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED)) + if (device_link_flag_is_sync_state_only(link->flags)) continue; device_reorder_to_tail(link->consumer, NULL); } @@ -684,7 +688,8 @@ postcore_initcall(devlink_class_init); DL_FLAG_AUTOREMOVE_SUPPLIER | \ DL_FLAG_AUTOPROBE_CONSUMER | \ DL_FLAG_SYNC_STATE_ONLY | \ - DL_FLAG_INFERRED) + DL_FLAG_INFERRED | \ + DL_FLAG_CYCLE) #define DL_ADD_VALID_FLAGS (DL_MANAGED_LINK_FLAGS | DL_FLAG_STATELESS | \ DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE) @@ -753,8 +758,6 @@ struct device_link *device_link_add(struct device *consumer, if (!consumer || !supplier || consumer == supplier || flags & ~DL_ADD_VALID_FLAGS || (flags & DL_FLAG_STATELESS && flags & DL_MANAGED_LINK_FLAGS) || - (flags & DL_FLAG_SYNC_STATE_ONLY && - (flags & ~DL_FLAG_INFERRED) != DL_FLAG_SYNC_STATE_ONLY) || (flags & DL_FLAG_AUTOPROBE_CONSUMER && flags & (DL_FLAG_AUTOREMOVE_CONSUMER | DL_FLAG_AUTOREMOVE_SUPPLIER))) @@ -770,6 +773,10 @@ struct device_link *device_link_add(struct device *consumer, if (!(flags & DL_FLAG_STATELESS)) flags |= DL_FLAG_MANAGED; + if (flags & DL_FLAG_SYNC_STATE_ONLY && + !device_link_flag_is_sync_state_only(flags)) + return NULL; + device_links_write_lock(); device_pm_lock(); @@ -1729,7 +1736,7 @@ static void fw_devlink_relax_link(struct device_link *link) if (!(link->flags & DL_FLAG_INFERRED)) return; - if (link->flags == (DL_FLAG_MANAGED | FW_DEVLINK_FLAGS_PERMISSIVE)) + if (device_link_flag_is_sync_state_only(link->flags)) return; pm_runtime_drop_link(link); @@ -1853,8 +1860,8 @@ static int fw_devlink_relax_cycle(struct device *con, void *sup) return ret; list_for_each_entry(link, &con->links.consumers, s_node) { - if ((link->flags & ~DL_FLAG_INFERRED) == - (DL_FLAG_SYNC_STATE_ONLY | DL_FLAG_MANAGED)) + if (!(link->flags & DL_FLAG_CYCLE) && + device_link_flag_is_sync_state_only(link->flags)) continue; if (!fw_devlink_relax_cycle(link->consumer, sup)) @@ -1863,6 +1870,7 @@ static int fw_devlink_relax_cycle(struct device *con, void *sup) ret = 1; fw_devlink_relax_link(link); + link->flags |= DL_FLAG_CYCLE; } return ret; } diff --git a/include/linux/device.h b/include/linux/device.h index 44e3acae7b36..f4d20655d2d7 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -328,6 +328,7 @@ enum device_link_state { #define DL_FLAG_MANAGED BIT(6) #define DL_FLAG_SYNC_STATE_ONLY BIT(7) #define DL_FLAG_INFERRED BIT(8) +#define DL_FLAG_CYCLE BIT(9) /** * enum dl_dev_state - Device driver presence tracking information.