[PATCH] Revert "i2c: designware: defer probe if child GpioInt controllers are not bound"
Hardik Prakash <[email protected]>
| Newsgroups | org.kernel.vger.linux-gpio,org.kernel.vger.linux-i2c,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
This reverts commit 0a4bb2abc3e56d7be6e69b050c88ba52c87e22bf. The reverted commit causes a regression on ThinkPad T14s Gen 4 (AMD): the touchpad's I2C controller fails with lost arbitration errors, because it delays i2c-designware's probe by roughly 500ms, which shifts the touchpad's first HID descriptor fetch into a window where the platform's embedded controller is still acting as a secondary I2C bus master. Debug tracing confirms the GpioInt dependency check itself behaves correctly (it defers appropriately and confirms the GPIO controller is bound); the arbitration failure happens roughly a second after the check passes, when i2c_hid_acpi's own probe attempts its first transaction. The original fix is still needed for the Lenovo Yoga 7 14AGP11 touchscreen race the commit addressed, but a corrected version will be resubmitted once the EC bus-mastering interaction is understood and handled properly, rather than reintroducing a different regression on more widely-used ThinkPad hardware in the meantime. Reported-by: Thorsten Leemhuis <[email protected]> Closes: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Hardik Prakash <[email protected]> --- drivers/i2c/busses/i2c-designware-platdrv.c | 80 --------------------- 1 file changed, 80 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index c8a203fff4d1..6d6e81242f74 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -8,14 +8,12 @@ * 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> #include <linux/dmi.h> #include <linux/err.h> #include <linux/errno.h> -#include <linux/gpio/driver.h> #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -132,80 +130,6 @@ static int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev) return 0; } -#if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB) -/* - * Check whether an ACPI GpioInt resource's referenced GPIO controller - * has finished probing. Resources with no named controller (resource - * source string) are skipped, since they can't be resolved to a - * struct device. - */ -static int check_gpioint_resource(struct acpi_resource *ares, void *data) -{ - struct acpi_resource_gpio *agpio; - struct acpi_device *gpio_adev; - struct device *gpio_dev; - acpi_handle handle; - acpi_status status; - - if (!acpi_gpio_get_irq_resource(ares, &agpio)) - return 1; /* not a GpioInt resource, skip */ - - if (!agpio->resource_source.string_length) - return 1; /* no named controller, skip */ - - status = acpi_get_handle(NULL, agpio->resource_source.string_ptr, &handle); - if (ACPI_FAILURE(status)) - return 1; - - gpio_adev = acpi_fetch_acpi_dev(handle); - if (!gpio_adev) - return 1; - - struct gpio_device *gdev __free(gpio_device_put) = - gpio_device_find_by_fwnode(acpi_fwnode_handle(gpio_adev)); - if (!gdev) - return -EPROBE_DEFER; /* controller not registered yet: abort walk */ - - gpio_dev = gpio_device_to_device(gdev)->parent; - - guard(device)(gpio_dev); - if (!device_is_bound(gpio_dev)) - return -EPROBE_DEFER; /* controller not bound yet: abort walk */ - - return 1; /* bound, skip adding to resource list, continue walk */ -} - -static int check_child_gpioint(struct acpi_device *adev, void *data) -{ - LIST_HEAD(res_list); - int ret; - - ret = acpi_dev_get_resources(adev, &res_list, check_gpioint_resource, NULL); - if (ret < 0) - return ret; - - acpi_dev_free_resource_list(&res_list); - - return 0; -} - -static int i2c_dw_check_gpio_dependencies(struct device *dev) -{ - struct acpi_device *adev; - - adev = ACPI_COMPANION(dev); - if (!adev) - return 0; - - return acpi_dev_for_each_child(adev, check_child_gpioint, NULL); -} -#else -static int i2c_dw_check_gpio_dependencies(struct device *dev) -{ - return 0; -} -#endif /* CONFIG_ACPI && CONFIG_GPIOLIB */ - static int dw_i2c_plat_probe(struct platform_device *pdev) { u32 flags = (uintptr_t)device_get_match_data(&pdev->dev); @@ -214,10 +138,6 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) struct dw_i2c_dev *dev; int irq, ret; - ret = i2c_dw_check_gpio_dependencies(device); - if (ret) - return ret; - irq = platform_get_irq_optional(pdev, 0); if (irq == -ENXIO) flags |= ACCESS_POLLING; base-commit: 3d6d817622b0a9721e3cc404df3469171582be13 -- 2.55.0