* [PATCH v7 0/1] i2c: designware: defer probe if child GpioInt controllers are not bound
@ 2026-05-26 10:52 Hardik Prakash
2026-05-26 10:52 ` [PATCH v7 1/1] " Hardik Prakash
0 siblings, 1 reply; 3+ messages in thread
From: Hardik Prakash @ 2026-05-26 10:52 UTC (permalink / raw)
To: linux-i2c
Cc: linux-gpio, wsa, andriy.shevchenko, mario.limonciello, brgl,
basavaraj.natikar, linusw, Hardik Prakash
Patch 1/2 (pinctrl-amd GPIO IRQ fix) is already in Linus Walleij's
tree, but testing confirms it is not needed with this approach — v7
alone is sufficient. Linus Walleij may wish to drop patch 1.
The root cause: i2c_designware probes AMDI0010:02 before pinctrl-amd
completes. Dynamic debug tracing confirmed the race:
0.285952 amd_gpio_probe: registering gpiochip <- GPIO chip visible
0.287121 amd_gpio_probe: requesting parent IRQ <- probe still running
0.301454 AMDI0010:02 dw_i2c_plat_probe: start <- races here
2.348157 lost arbitration
This patch adds a generic check that walks ACPI child devices, finds
any GpioInt resources, and defers probe if the referenced GPIO
controllers are not yet fully bound. No DMI matching required.
Tested on Lenovo Yoga 7 14AGP11 (83TD), Fedora 44, kernel 7.1.0-rc1+.
Touch and stylus fully functional with v7 alone (without patch 1).
v7:
- Fix unused 'ret' variable in check_child_gpioint() (kernel test robot)
- Replace BugLink: with Link: (Bartosz Golaszewski)
- Add Reported-by and Closes tags for kernel test robot warning
v6:
- Replace DMI-specific deferral with generic GpioInt dependency check
walking ACPI child devices (suggested by Mario Limonciello)
v5:
- Add blank line before #include <linux/acpi.h> (Bartosz Golaszewski)
- Use scoped_guard(device, gpio_dev) (Bartosz Golaszewski)
v4:
- Rebase onto Linus Walleij's tree (patch 1 already there)
- Use --base so series is correctly 1/1 (Andy Shevchenko)
v3:
- Fix variable declaration style (Andy Shevchenko)
- Add BugLink tag (Andy Shevchenko)
- CC AMD engineers (Andy Shevchenko)
v2:
- Replace custom HID/UID lookup with acpi_dev_get_first_match_dev()
- Use device_is_bound() under device_lock() with explanatory comments
- Add Assisted-by tags per coding-assistants.rst
Kernel bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=221494
Related: https://bugzilla.kernel.org/show_bug.cgi?id=221454
Hardik Prakash (1):
i2c: designware: defer probe if child GpioInt controllers are not
bound
drivers/i2c/busses/i2c-designware-platdrv.c | 156 ++++++++++++++++++++
1 file changed, 156 insertions(+)
base-commit: 3812a9e84265a5cdd90d29fe8d97a023e91fb945
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v7 1/1] i2c: designware: defer probe if child GpioInt controllers are not bound
2026-05-26 10:52 [PATCH v7 0/1] i2c: designware: defer probe if child GpioInt controllers are not bound Hardik Prakash
@ 2026-05-26 10:52 ` Hardik Prakash
2026-05-26 10:56 ` Bartosz Golaszewski
0 siblings, 1 reply; 3+ messages in thread
From: Hardik Prakash @ 2026-05-26 10:52 UTC (permalink / raw)
To: linux-i2c
Cc: linux-gpio, wsa, andriy.shevchenko, mario.limonciello, brgl,
basavaraj.natikar, linusw, Hardik Prakash, kernel test robot
I2C controllers may have child devices with GpioInt resources that
depend on GPIO controllers to be fully initialized. If the I2C
controller probes and enumerates children before the referenced GPIO
controller has completed probe, GPIO interrupts may not be properly
configured, leading to device failures.
On Lenovo Yoga 7 14AGP11, the WACF2200 touchscreen (child of
AMDI0010:02) has a GpioInt resource pointing to GPIO 157 on the
pinctrl-amd controller (AMDI0030:00). When i2c-designware probes
AMDI0010:02 before pinctrl-amd finishes initializing, I2C transactions
occur before the GPIO IRQ quirk in amd_gpio_probe() has run, causing:
i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost arbitration
Add a generic dependency check in i2c-designware that walks ACPI child
devices, identifies any GpioInt resources, resolves the referenced GPIO
controllers, and defers probe if those controllers are not yet bound.
This ensures GPIO controllers complete initialization (including IRQ
setup and quirks) before I2C child enumeration begins, fixing the race
without device-specific quirks or DMI matching.
The probe ordering race was confirmed via dynamic debug tracing:
0.285952 amd_gpio_probe: registering gpiochip <- GPIO chip visible
0.287121 amd_gpio_probe: requesting parent IRQ <- probe still running
0.301454 AMDI0010:02 dw_i2c_plat_probe: start <- races here
2.348157 lost arbitration
Suggested-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Hardik Prakash <hardikprakash.official@gmail.com>
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: GPT-Codex:gpt-5.2-codex
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202605240959.Kcf1lIg4-lkp@intel.com/
Link: https://bugzilla.kernel.org/show_bug.cgi?id=221494
---
drivers/i2c/busses/i2c-designware-platdrv.c | 156 ++++++++++++++++++++
1 file changed, 156 insertions(+)
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 3351c4a9ef11..1c01b0460385 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -8,6 +8,8 @@
* Copyright (C) 2007 MontaVista Software Inc.
* Copyright (C) 2009 Provigent Ltd.
*/
+
+#include <linux/acpi.h>
#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/delay.h>
@@ -130,6 +132,152 @@ static int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev)
return 0;
}
+#ifdef CONFIG_ACPI
+struct gpio_dep_ctx {
+ struct list_head gpio_controllers;
+ int ret;
+};
+
+struct gpio_controller_ref {
+ struct list_head node;
+ char *path;
+};
+
+static int check_gpioint_resource(struct acpi_resource *ares, void *data)
+{
+ struct gpio_dep_ctx *ctx = data;
+ struct acpi_resource_gpio *agpio;
+ struct gpio_controller_ref *ref, *tmp;
+ bool found = false;
+
+ if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
+ return 1;
+
+ agpio = &ares->data.gpio;
+ if (agpio->connection_type != ACPI_RESOURCE_GPIO_TYPE_INT)
+ return 1;
+
+ /* Check if we've already tracked this GPIO controller */
+ list_for_each_entry(tmp, &ctx->gpio_controllers, node) {
+ if (!strcmp(tmp->path, agpio->resource_source.string_ptr)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ ref = kzalloc(sizeof(*ref), GFP_KERNEL);
+ if (!ref) {
+ ctx->ret = -ENOMEM;
+ return 0;
+ }
+
+ ref->path = kstrdup(agpio->resource_source.string_ptr, GFP_KERNEL);
+ if (!ref->path) {
+ kfree(ref);
+ ctx->ret = -ENOMEM;
+ return 0;
+ }
+
+ list_add_tail(&ref->node, &ctx->gpio_controllers);
+ }
+
+ return 1;
+}
+
+static int check_child_gpioint(struct acpi_device *adev, void *data)
+{
+ struct gpio_dep_ctx *ctx = data;
+ struct list_head res_list;
+
+ INIT_LIST_HEAD(&res_list);
+
+ acpi_dev_get_resources(adev, &res_list, check_gpioint_resource, ctx);
+ acpi_dev_free_resource_list(&res_list);
+
+ if (ctx->ret < 0)
+ return ctx->ret;
+
+ return 0;
+}
+
+static int i2c_dw_check_gpio_dependencies(struct device *dev)
+{
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+ struct gpio_dep_ctx ctx = { .ret = 0 };
+ struct gpio_controller_ref *ref, *tmp;
+ int ret = 0;
+
+ if (!adev)
+ return 0;
+
+ INIT_LIST_HEAD(&ctx.gpio_controllers);
+
+ /* Walk all child devices and collect GpioInt controller references */
+ ret = acpi_dev_for_each_child(adev, check_child_gpioint, &ctx);
+ if (ret < 0 || ctx.ret < 0) {
+ ret = ctx.ret ?: ret;
+ goto cleanup;
+ }
+
+ /* For each GPIO controller, check if its parent device is bound */
+ list_for_each_entry(ref, &ctx.gpio_controllers, node) {
+ acpi_handle handle;
+ acpi_status status;
+ struct acpi_device *gpio_adev;
+ struct device *gpio_dev;
+ bool bound;
+
+ status = acpi_get_handle(NULL, ref->path, &handle);
+ if (ACPI_FAILURE(status))
+ continue;
+
+ gpio_adev = acpi_fetch_acpi_dev(handle);
+ if (!gpio_adev)
+ continue;
+
+ gpio_dev = acpi_get_first_physical_node(gpio_adev);
+ acpi_dev_put(gpio_adev);
+
+ if (!gpio_dev) {
+ ret = -EPROBE_DEFER;
+ goto cleanup;
+ }
+
+ /*
+ * Check if the GPIO controller's device is bound. If not,
+ * defer probe to ensure GPIO initialization (including IRQ
+ * setup and quirks) is complete before we enumerate I2C
+ * child devices.
+ */
+ scoped_guard(device, gpio_dev) {
+ bound = device_is_bound(gpio_dev);
+ }
+ if (!bound) {
+ put_device(gpio_dev);
+ ret = -EPROBE_DEFER;
+ goto cleanup;
+ }
+
+ put_device(gpio_dev);
+ }
+
+cleanup:
+ list_for_each_entry_safe(ref, tmp, &ctx.gpio_controllers, node) {
+ list_del(&ref->node);
+ kfree(ref->path);
+ kfree(ref);
+ }
+
+ return ret;
+}
+#else
+static int i2c_dw_check_gpio_dependencies(struct device *dev)
+{
+ return 0;
+}
+#endif /* CONFIG_ACPI */
+
static int dw_i2c_plat_probe(struct platform_device *pdev)
{
u32 flags = (uintptr_t)device_get_match_data(&pdev->dev);
@@ -138,6 +286,14 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
struct dw_i2c_dev *dev;
int irq, ret;
+ /*
+ * Check if any child devices have GpioInt resources, and if so,
+ * defer probe until those GPIO controllers are fully bound.
+ */
+ ret = i2c_dw_check_gpio_dependencies(device);
+ if (ret)
+ return ret;
+
irq = platform_get_irq_optional(pdev, 0);
if (irq == -ENXIO)
flags |= ACCESS_POLLING;
--
2.54.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v7 1/1] i2c: designware: defer probe if child GpioInt controllers are not bound
2026-05-26 10:52 ` [PATCH v7 1/1] " Hardik Prakash
@ 2026-05-26 10:56 ` Bartosz Golaszewski
0 siblings, 0 replies; 3+ messages in thread
From: Bartosz Golaszewski @ 2026-05-26 10:56 UTC (permalink / raw)
To: Hardik Prakash
Cc: linux-gpio, wsa, andriy.shevchenko, mario.limonciello, brgl,
basavaraj.natikar, linusw, kernel test robot, linux-i2c
On Tue, 26 May 2026 12:52:10 +0200, Hardik Prakash
<hardikprakash.official@gmail.com> said:
> I2C controllers may have child devices with GpioInt resources that
> depend on GPIO controllers to be fully initialized. If the I2C
> controller probes and enumerates children before the referenced GPIO
> controller has completed probe, GPIO interrupts may not be properly
> configured, leading to device failures.
>
> On Lenovo Yoga 7 14AGP11, the WACF2200 touchscreen (child of
> AMDI0010:02) has a GpioInt resource pointing to GPIO 157 on the
> pinctrl-amd controller (AMDI0030:00). When i2c-designware probes
> AMDI0010:02 before pinctrl-amd finishes initializing, I2C transactions
> occur before the GPIO IRQ quirk in amd_gpio_probe() has run, causing:
>
> i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost arbitration
>
> Add a generic dependency check in i2c-designware that walks ACPI child
> devices, identifies any GpioInt resources, resolves the referenced GPIO
> controllers, and defers probe if those controllers are not yet bound.
>
> This ensures GPIO controllers complete initialization (including IRQ
> setup and quirks) before I2C child enumeration begins, fixing the race
> without device-specific quirks or DMI matching.
>
> The probe ordering race was confirmed via dynamic debug tracing:
>
> 0.285952 amd_gpio_probe: registering gpiochip <- GPIO chip visible
> 0.287121 amd_gpio_probe: requesting parent IRQ <- probe still running
> 0.301454 AMDI0010:02 dw_i2c_plat_probe: start <- races here
> 2.348157 lost arbitration
>
> Suggested-by: Mario Limonciello <mario.limonciello@amd.com>
> Signed-off-by: Hardik Prakash <hardikprakash.official@gmail.com>
> Assisted-by: Claude:claude-sonnet-4-6
> Assisted-by: GPT-Codex:gpt-5.2-codex
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202605240959.Kcf1lIg4-lkp@intel.com/
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=221494
> ---
Please collect review tags, I already left my A-b under the last revision.
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Hint: try to give others some time to respond, don't resend a new version
immediately after each review email from maintainers.
Bart
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-05-26 10:57 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-26 10:52 [PATCH v7 0/1] i2c: designware: defer probe if child GpioInt controllers are not bound Hardik Prakash
2026-05-26 10:52 ` [PATCH v7 1/1] " Hardik Prakash
2026-05-26 10:56 ` Bartosz Golaszewski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox