From patchwork Thu May 26 08:15:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Saravana Kannan X-Patchwork-Id: 576659 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 C0F2AC433FE for ; Thu, 26 May 2022 08:16:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346773AbiEZIQp (ORCPT ); Thu, 26 May 2022 04:16:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37330 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346600AbiEZIQQ (ORCPT ); Thu, 26 May 2022 04:16:16 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A971849CAE for ; Thu, 26 May 2022 01:16:14 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-2f8398e99dcso7515437b3.9 for ; Thu, 26 May 2022 01:16:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=LHvrfQT4UXFPIW7HvFCMhDyzwcScgNhuNK8AAkQqhh0=; b=ckTLEE9Ka8zRBQWZF8bw1bzPyohHSB7lFDGLGx8zTrvE1U6jlLS2u8eGVyiyeggEvU f2EkV92DxtJdRwumDctwEA2IQx70gREKkuzwEB+3OV15TZsv4nnJNeHpcR3jy+FuEHO1 E+wXrf/OpSIAmM7QLQFDf1+Hl/jJe7k56R5tSxkJdxRlRw2RMnjPZSIzlQ613IfRTFOa Zx8mX+wckPdc1dHZYVMnSMTwB7wl2UW03yvyEnDwGVANY6EkvB+fRXiLFfl04V8Uv38Y DXO0NJt9s3+k0LJaHseJ6m+c87C0hU/eJug6HuK1f5WfFNhgvCbmyh04c4hNdwY8HvkX PXvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=LHvrfQT4UXFPIW7HvFCMhDyzwcScgNhuNK8AAkQqhh0=; b=3nDs6QaFVyIXdUqye3PtYwrBtqOWCDfc/2D+QtCMr3UA2aRjxG2MSl7M0Cvq7JNy3M 9u6X/s74GIg/mVqJP4m7gg5zHq9z/PdhpvR0qjbHlKi0IQ/nYj4ei5W/aKBwaw5nIcBe ojtGBroCBy7DjprvqzJZEgIkQTWo+UB1ofEzC0QF75tnCtAR16rMH3+5RdG2NHksdpX2 zM9/gNj+jc0nAj48s13OjWJ6yuo63IqfKd5WLPuyZ8aYI3tGUTb1oQCIL+1fNuHvi8lR XoGqpI7uROywoygRMGfoKKezl91dkKbCGn9GUrXjsrlW999QsD8OlSEb9rVMr9YULjyb eAWg== X-Gm-Message-State: AOAM531WmmhfHVYprCip5daOIptBMfj9PplRqO/Uj+vvqJDPmrtE45nw /pV2pyftYNkR/xeFQL1NcCNfu2DE72Y5B1o= X-Google-Smtp-Source: ABdhPJw4+9jAT07QlqTfVdN89DFF1UyFTJg5uRAxow4srxchUBWqQAUPj+CYeVjLPhmM3eADjwvBI1mMP+o/3L0= X-Received: from saravanak.san.corp.google.com ([2620:15c:2d:3:ff1f:a3b7:b6de:d30f]) (user=saravanak job=sendgmr) by 2002:a25:928b:0:b0:64a:f505:427f with SMTP id y11-20020a25928b000000b0064af505427fmr33415597ybl.146.1653552974289; Thu, 26 May 2022 01:16:14 -0700 (PDT) Date: Thu, 26 May 2022 01:15:46 -0700 In-Reply-To: <20220526081550.1089805-1-saravanak@google.com> Message-Id: <20220526081550.1089805-8-saravanak@google.com> Mime-Version: 1.0 References: <20220526081550.1089805-1-saravanak@google.com> X-Mailer: git-send-email 2.36.1.124.g0e6072fb45-goog Subject: [RFC PATCH v1 7/9] driver core: Add fw_devlink_unblock_may_probe() helper function From: Saravana Kannan To: Greg Kroah-Hartman , "Rafael J. Wysocki" , Kevin Hilman , Ulf Hansson , Len Brown , Pavel Machek , Joerg Roedel , Will Deacon , Andrew Lunn , Heiner Kallweit , Russell King , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Linus Walleij , Andy Shevchenko , Daniel Scally , Heikki Krogerus , Sakari Ailus , Hideaki YOSHIFUJI , David Ahern , Len Brown Cc: Saravana Kannan , Mark Brown , Rob Herring , Geert Uytterhoeven , Yoshihiro Shimoda , John Stultz , Nathan Chancellor , Sebastian Andrzej Siewior , kernel-team@android.com, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, iommu@lists.linux-foundation.org, netdev@vger.kernel.org, linux-gpio@vger.kernel.org, linux-acpi@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org This function can be used during the kernel boot sequence to forcefully override fw_devlink=on and unblock the probing of all devices that have a driver. It's mainly meant to be called from late_initcall() or late_initcall_sync() where a device needs to probe before the kernel can mount rootfs. Signed-off-by: Saravana Kannan --- drivers/base/base.h | 1 + drivers/base/core.c | 58 ++++++++++++++++++++++++++++++++++++++++++ drivers/base/dd.c | 2 +- include/linux/fwnode.h | 2 ++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index ab71403d102f..b3a43a164dcd 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -160,6 +160,7 @@ extern int devres_release_all(struct device *dev); extern void device_block_probing(void); extern void device_unblock_probing(void); extern void deferred_probe_extend_timeout(void); +extern void driver_deferred_probe_trigger(void); /* /sys/devices directory */ extern struct kset *devices_kset; diff --git a/drivers/base/core.c b/drivers/base/core.c index 7672f23231c1..7ff7fbb00643 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1655,6 +1655,64 @@ void fw_devlink_drivers_done(void) device_links_write_unlock(); } +static int fw_devlink_may_probe(struct device *dev, void *data) +{ + struct device_link *link = to_devlink(dev); + + if (!link->supplier->can_match && link->consumer->can_match) + fw_devlink_relax_link(link); + + return 0; +} + +/** + * fw_devlink_unblock_may_probe - Force unblock any device that has a driver + * + * This function is more of a sledge hammer than a scalpel. Use this very + * sparingly. + * + * Some devices might need to be probed and bound successfully before the kernel + * boot sequence can finish and move on to init/userspace. For example, a + * network interface might need to be bound to be able to mount a NFS rootfs. + * + * With fw_devlink=on by default, some of these devices might be blocked from + * probing because they are waiting on a optional supplier that doesn't have a + * driver. While fw_devlink will eventually identify such devices and unblock + * the probing automatically, it might be too late by the time it unblocks the + * probing of devices. For example, the IP4 autoconfig might timeout before + * fw_devlink unblocks probing of the network interface. This function is + * available to unblock the probing of such devices. + * + * Since there's no easy way to know which unprobed device needs to probe for + * boot to succeed, this function makes sure fw_devlink doesn't block any device + * that has a driver at the point in time this function is called. + * + * It does this by relaxing (fw_devlink=permissive behavior) all the device + * links created by fw_devlink where the consumer has a driver and the supplier + * doesn't have a driver. + * + * It's extremely unlikely that a proper use of this function will be outside of + * an initcall. So, until a case is made for that, this function is + * intentionally marked with __init. + */ +void __init fw_devlink_unblock_may_probe(void) +{ + struct device_link *link, *ln; + + if (!fw_devlink_flags || fw_devlink_is_permissive()) + return; + + /* Wait for current probes to finish to limit impact. */ + wait_for_device_probe(); + + device_links_write_lock(); + class_for_each_device(&devlink_class, NULL, NULL, + fw_devlink_may_probe); + device_links_write_unlock(); + + driver_deferred_probe_trigger(); +} + static void fw_devlink_unblock_consumers(struct device *dev) { struct device_link *link; diff --git a/drivers/base/dd.c b/drivers/base/dd.c index f963d9010d7f..af8138d44e6c 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -172,7 +172,7 @@ static bool driver_deferred_probe_enable; * changes in the midst of a probe, then deferred processing should be triggered * again. */ -static void driver_deferred_probe_trigger(void) +void driver_deferred_probe_trigger(void) { if (!driver_deferred_probe_enable) return; diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index 9a81c4410b9f..0770edda7068 100644 --- a/include/linux/fwnode.h +++ b/include/linux/fwnode.h @@ -13,6 +13,7 @@ #include #include #include +#include struct fwnode_operations; struct device; @@ -199,5 +200,6 @@ extern bool fw_devlink_is_strict(void); int fwnode_link_add(struct fwnode_handle *con, struct fwnode_handle *sup); void fwnode_links_purge(struct fwnode_handle *fwnode); void fw_devlink_purge_absent_suppliers(struct fwnode_handle *fwnode); +void __init fw_devlink_unblock_may_probe(void); #endif