Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpiolib: acpi: Fix failed in acpi_gpiochip_find() by adding parent node match

Previous patch modified the standard used by acpi_gpiochip_find()
to match device nodes. Using the device node set in gc->gpiodev->d-
ev instead of gc->parent.

However, there is a situation in gpio-dwapb where the GPIO device
driver will set gc->fwnode for each port corresponding to a child
node under a GPIO device, so gc->gpiodev->dev will be assigned the
value of each child node in gpiochip_add_data().

gpio-dwapb.c:
128,31 static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
struct dwapb_port_property *pp,
unsigned int offs);
port->gc.fwnode = pp->fwnode;

693,39 static int dwapb_gpio_probe;
err = dwapb_gpio_add_port(gpio, &pdata->properties[i], i);

When other drivers request GPIO pin resources through the GPIO device
node provided by ACPI (corresponding to the parent node), the change
of the matching object to gc->gpiodev->dev in acpi_gpiochip_find()
only allows finding the value of each port (child node), resulting
in a failed request.

Reapply the condition of using gc->parent for match in acpi_gpio-
chip_find() in the code can compatible with the problem of gpio-dwapb,
and will not affect the two cases mentioned in the patch:
1. There is no setting for gc->fwnode.
2. The case that depends on using gc->fwnode for match.

Fixes: 5062e4c14b75 ("gpiolib: acpi: use the fwnode in acpi_gpiochip_find()")
Fixes: 067dbc1ea5ce ("gpiolib: acpi: Don't use GPIO chip fwnode in acpi_gpiochip_find()")
Signed-off-by: Devyn Liu <liudingyuan@huawei.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Tested-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

authored by

Devyn Liu and committed by
Andy Shevchenko
adbc49a5 4bcc9bba

+18 -1
+18 -1
drivers/gpio/gpiolib-acpi.c
··· 128 128 129 129 static int acpi_gpiochip_find(struct gpio_chip *gc, const void *data) 130 130 { 131 - return device_match_acpi_handle(&gc->gpiodev->dev, data); 131 + /* First check the actual GPIO device */ 132 + if (device_match_acpi_handle(&gc->gpiodev->dev, data)) 133 + return true; 134 + 135 + /* 136 + * When the ACPI device is artificially split to the banks of GPIOs, 137 + * where each of them is represented by a separate GPIO device, 138 + * the firmware node of the physical device may not be shared among 139 + * the banks as they may require different values for the same property, 140 + * e.g., number of GPIOs in a certain bank. In such case the ACPI handle 141 + * of a GPIO device is NULL and can not be used. Hence we have to check 142 + * the parent device to be sure that there is no match before bailing 143 + * out. 144 + */ 145 + if (gc->parent) 146 + return device_match_acpi_handle(gc->parent, data); 147 + 148 + return false; 132 149 } 133 150 134 151 /**