On Mon, Jun 08, 2026 at 16:18, Borah, Chaitanya Kumar wrote: > This patch seems to cause a regression in our CI. Few of the machines > are unable to boot to ssh console and therefore hindering our test > execution. Bisect points to this patch and reverting this patch seems > to fix the issue.
Thank you for the report and the log. The putty log shows the kernel panic: "Timeout: Not all CPUs entered broadcast exception handler" after what appears to be a probe deferral loop causing CPU starvation. Andy Shevchenko already identified code issues with this patch on June 3rd and requested Linus Walleij drop it from his tree. The patch has not been fixed yet -- it needs a proper rewrite addressing NULL pointer dereferences and error path issues before it is safe to apply. Linus, could you please drop commit ef76a3a28c79 from your fixes tree? The regression affects multiple machines including Intel CI and Nathan Chancellor's test systems. I will send a corrected version once the rewrite is complete. Sorry for the disruption. Thanks, Hardik On Tue, 9 Jun 2026 at 16:18, Borah, Chaitanya Kumar <[email protected]> wrote: > > Hello Hardik, > > On 5/29/2026 3:38 PM, Hardik Prakash wrote: > > 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 > > > > This patch seems to cause a regression in our CI [1]. Few of the machine > are unable to boot to ssh console and therefore hindering our test exection. > > The issue first appeared with next-20260601 [2]. > > Bisect points to this patch and reverting this patch seems to fix the issue. > > Putty logs are attached. > > Could you please check why the patch causes this regression and provide > a fix if necessary? > > == > Chaitanya > > [1] https://intel-gfx-ci.01.org/tree/linux-next/combined-alt.html? > [2] > https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20260601 > > > Suggested-by: Mario Limonciello <[email protected]> > > Signed-off-by: Hardik Prakash <[email protected]> > > Acked-by: Bartosz Golaszewski <[email protected]> > > Reviewed-by: Mario Limonciello (AMD) <[email protected]> > > Assisted-by: Claude:claude-sonnet-4-6 > > Assisted-by: GPT-Codex:gpt-5.2-codex > > Reported-by: kernel test robot <[email protected]> > > Closes: > > https://lore.kernel.org/oe-kbuild-all/[email protected]/ > > 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;
