From nobody Thu Apr 2 04:20:13 2026 Received: from mail-dl1-f50.google.com (mail-dl1-f50.google.com [74.125.82.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 37BD33D666A for ; Mon, 30 Mar 2026 14:29:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774880984; cv=none; b=seQNsOx/4k6XNqp5wMLTnX6JSL7sZMe0YfbgjnV0/OkftiUjlNNY3R591r8BtV+enSJVTp3KNAbO4UcCV/F4VBvXiAHsWu6yAmhI9kpn3kQk95eV9vuAvr5ONVVoEfoEkGgh8opffw+S4H7C4VHAaWh7C+/5UtpMROP1tGXfzk4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774880984; c=relaxed/simple; bh=8LQZSocESOF3veZ/bfrXbhh0O+so24+/tbM7fVlpCr0=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=oD4td+4HtaGqiFoCu+t59Xfov/JZR+S0+wgXP79b/Zfxy33jLs7HeQ2BLUOcKuiIVD9accElyfRBWS3XGXWT4q7p2QrIROuE/RZlFMj26ppoIaYBcc9xsW0UvX4qCX/zq72QY6DAemZ9onsEkY7MoQXbMKlzTwhq/a95aqHBAaU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=GacCgKhW; arc=none smtp.client-ip=74.125.82.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="GacCgKhW" Received: by mail-dl1-f50.google.com with SMTP id a92af1059eb24-12a80c36350so4865125c88.1 for ; Mon, 30 Mar 2026 07:29:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1774880980; x=1775485780; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=ACJ6Cr/IS11gucQGUIuPydXkCtkwKZa4TuMCqVkix8k=; b=GacCgKhWonS2gcGcaXAZZX+ebDO0j0yGDMq9nmNMC9EUn3LJ2Q+oApqFXR4gjhpVAR gnhsKC6VorgLcx2XgFYJV+hibTrNWzJQQie4IDrC9n1Orq5U44pyvMQnvCOWiDH0gffL idNXzwflqAVPdaAhWJm05Xol6ad3ZC3m98uXo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774880980; x=1775485780; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=ACJ6Cr/IS11gucQGUIuPydXkCtkwKZa4TuMCqVkix8k=; b=PdLU6k3yMZ2XiVH5RFhQZrqSsmkTaw57Inah3VydkTAoqrea8GFL0GhuM8s61FHiLY QH0h8W/qyemys14rJXeEPdw6vQRpv+o5LcaNgw+3pNP8DrnEy/DL+p0rgjx20qiCAwju En/HTQD1KPu6iXlwYidMd7A5O3DcxYJXGoST+YVMPmzCr/ZiScZkjJkmrjSwmfdO3jGj L8KVAyb63F28/EbqzTyuB+avLwgoGkZukyK3E1hWJGsOdTRIvZ8H2XcMznhDDpwKaEvU BW9lUKTqB4C2c+Hz4X8g930Fe9T9tASoj4N4F3iQYDFj3MLMfSM10MzTN2+8jfi+HO99 STAQ== X-Forwarded-Encrypted: i=1; AJvYcCWIdE5pqDHJV+EKNvy9Ri2Q26Z2UZQk6/H1nklN5Wk8tyiZoq8LAHAgG8UhPNeBTUVF5NMZTlkn2UWJjKI=@vger.kernel.org X-Gm-Message-State: AOJu0YxwqMeXtFcPuuSI4AkkdHbYa2LWioGmAfdRGYQ9Yke6l/Wx5R0+ NR+8PsUYQlxJp3xzKT6FTGOxbFixV/gGibRWQfLgHEGYeODsRe76GoBMbhfd7GpyRg== X-Gm-Gg: ATEYQzzBg+l7h7LDaRbXPReRnd7L28pV69+ptuHHYeABacd4pvNOXaDa6VcPJyABG+X gGtQ5sEY6OYba6+gPmXMX0BXA8Lqfx5eivFhF3sFqf5hc2gsmMIAyhGYaSgNS2jja4yk1W6vUcf oWS9lScJ0Vxv2mxEKyePQTj0R4brSiiN4UVWosL+8Xkjw5C0Qvllv3Qa2u2yRYw/FD8nr2wxIbL 0fWatFp8kP6tlzlF+h1zwMdPRzRrcJY3y+H31N+BBZKzsz0KkSzgKCJlf4FctS+B3ZFecOlDAYN PiLnNl2CUFYZh3dou1313cGf2KvOfO/X7kddHX7MT/P+uqM7sy7XNh6qL0rcI0WrPrGujWhCOQd tS+nrqLZrWTLCa8gft5SSiIe0DnCJPXBF1cvvVM48/9TLWts3u7zA541YijBWRUW6SabqPYcIF5 /lm81mKVcjthX2X17/UjTJe73BhVLQV+pM1ggbTvBK0+t4gPWoN4uUMFJyvOi000rA1FonCHJs1 E20Mhx07B8= X-Received: by 2002:a05:7022:628c:b0:128:d471:8c1 with SMTP id a92af1059eb24-12ab2890739mr6624565c88.17.1774880980067; Mon, 30 Mar 2026 07:29:40 -0700 (PDT) Received: from dianders.sjc.corp.google.com ([2a00:79e0:2e7c:8:f4ab:830d:18d1:e45b]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-12aba581027sm10665132c88.4.2026.03.30.07.29.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Mar 2026 07:29:38 -0700 (PDT) From: Douglas Anderson To: Greg Kroah-Hartman , "Rafael J . Wysocki" , Danilo Krummrich , Alan Stern Cc: Kay Sievers , Saravana Kannan , Douglas Anderson , stable@vger.kernel.org, driver-core@lists.linux.dev, linux-kernel@vger.kernel.org Subject: [PATCH v2] driver core: Don't let a device probe until it's ready Date: Mon, 30 Mar 2026 07:28:41 -0700 Message-ID: <20260330072839.v2.1.Id750b0fbcc94f23ed04b7aecabcead688d0d8c17@changeid> X-Mailer: git-send-email 2.53.0.1018.g2bb0e51243-goog Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The moment we link a "struct device" into the list of devices for the bus, it's possible probe can happen. This is because another thread can load the driver at any time and that can cause the device to probe. This has been seen in practice with a stack crawl that looks like this [1]: really_probe() __driver_probe_device() driver_probe_device() __driver_attach() bus_for_each_dev() driver_attach() bus_add_driver() driver_register() __platform_driver_register() init_module() [some module] do_one_initcall() do_init_module() load_module() __arm64_sys_finit_module() invoke_syscall() As a result of the above, it was seen that device_links_driver_bound() could be called for the device before "dev->fwnode->dev" was assigned. This prevented __fw_devlink_pickup_dangling_consumers() from being called which meant that other devices waiting on our driver's sub-nodes were stuck deferring forever. It's believed that this problem is showing up suddenly for two reasons: 1. Android has recently (last ~1 year) implemented an optimization to the order it loads modules [2]. When devices opt-in to this faster loading, modules are loaded one-after-the-other very quickly. This is unlike how other distributions do it. The reproduction of this problem has only been seen on devices that opt-in to Android's "parallel module loading". 2. Android devices typically opt-in to fw_devlink, and the most noticeable issue is the NULL "dev->fwnode->dev" in device_links_driver_bound(). fw_devlink is somewhat new code and also not in use by all Linux devices. Even though the specific symptom where "dev->fwnode->dev" wasn't assigned could be fixed by moving that assignment higher in device_add(), other parts of device_add() (like the call to device_pm_add()) are also important to run before probe. Only moving the "dev->fwnode->dev" assignment would likely fix the current symptoms but lead to difficult-to-debug problems in the future. Fix the problem by preventing probe until device_add() has run far enough that the device is ready to probe. If somehow we end up trying to probe before we're allowed, __driver_probe_device() will return -EPROBE_DEFER which will make certain the device is noticed. In the race condition that was seen with Android's faster module loading, we will temporarily add the device to the deferred list and then take it off immediately when device_add() probes the device. [1] Captured on a machine running a downstream 6.6 kernel [2] https://cs.android.com/android/platform/superproject/main/+/main:system= /core/libmodprobe/libmodprobe.cpp?q=3DLoadModulesParallel Cc: stable@vger.kernel.org Fixes: 2023c610dc54 ("Driver core: add new device to bus's list before prob= ing") Signed-off-by: Douglas Anderson Reviewed-by: Alan Stern Reviewed-by: Rafael J. Wysocki (Intel) --- v1: https://lore.kernel.org/r/20260320200656.RFC.1.Id750b0fbcc94f23ed04b7ae= cabcead688d0d8c17@changeid This v2 feels like a very safe change. It doesn't change the ordering of any steps of probe and it _just_ prevents the early probe from happening. I ran tests where I turned the printout "Device not ready_to_probe" on and I could see the printout happening, evidence of the race occurring from other printouts, and things successfully being resolved. Changes in v2: - Instead of adjusting the ordering, use "ready_to_probe" flag drivers/base/core.c | 15 +++++++++++++++ drivers/base/dd.c | 12 ++++++++++++ include/linux/device.h | 3 +++ 3 files changed, 30 insertions(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index 09b98f02f559..4caa3fd1ecdb 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3688,6 +3688,21 @@ int device_add(struct device *dev) fw_devlink_link_device(dev); } =20 + /* + * The moment the device was linked into the bus's "klist_devices" in + * bus_add_device() then it's possible that probe could have been + * attempted in a different thread via userspace loading a driver + * matching the device. "ready_to_probe" being false would have blocked + * those attempts. Now that all of the above initialization has + * happened, unblock probe. If probe happens through another thread + * after this point but before bus_probe_device() runs then it's fine. + * bus_probe_device() -> device_initial_probe() -> __device_attach() + * will notice (under device_lock) that the device is already bound. + */ + device_lock(dev); + dev->ready_to_probe =3D true; + device_unlock(dev); + bus_probe_device(dev); =20 /* diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 37c7e54e0e4c..a1762254828f 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -848,6 +848,18 @@ static int __driver_probe_device(const struct device_d= river *drv, struct device if (dev->driver) return -EBUSY; =20 + /* + * In device_add(), the "struct device" gets linked into the subsystem's + * list of devices and broadcast to userspace (via uevent) before we're + * quite ready to probe. Those open pathways to driver probe before + * we've finished enough of device_add() to reliably support probe. + * Detect this and tell other pathways to try again later. device_add() + * itself will also try to probe immediately after setting + * "ready_to_probe". + */ + if (!dev->ready_to_probe) + return dev_err_probe(dev, -EPROBE_DEFER, "Device not ready_to_probe"); + dev->can_match =3D true; dev_dbg(dev, "bus: '%s': %s: matched device with driver %s\n", drv->bus->name, __func__, drv->name); diff --git a/include/linux/device.h b/include/linux/device.h index e65d564f01cd..e2f83384b627 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -553,6 +553,8 @@ struct device_physical_location { * @dma_skip_sync: DMA sync operations can be skipped for coherent buffers. * @dma_iommu: Device is using default IOMMU implementation for DMA and * doesn't rely on dma_ops structure. + * @ready_to_probe: If set to %true then device_add() has finished enough + * initialization that probe could be called. * * At the lowest level, every device in a Linux system is represented by an * instance of struct device. The device structure contains the information @@ -675,6 +677,7 @@ struct device { #ifdef CONFIG_IOMMU_DMA bool dma_iommu:1; #endif + bool ready_to_probe:1; }; =20 /** --=20 2.53.0.1018.g2bb0e51243-goog