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

gpio: Fix return value mismatch of function gpiod_get_from_of_node()

In case the requested gpio property is not found in the device tree, some
callers of gpiod_get_from_of_node() expect a return value of NULL, others
expect -ENOENT.
In particular devm_fwnode_get_index_gpiod_from_child() expects -ENOENT.
Currently it gets a NULL, which breaks the loop that tries all
gpio_suffixes. The result is that a gpio property is not found, even
though it is there.

This patch changes gpiod_get_from_of_node() to return -ENOENT instead
of NULL when the requested gpio property is not found in the device
tree. Additionally it modifies all calling functions to properly
evaluate the return value.

Another approach would be to leave the return value of
gpiod_get_from_of_node() as is and fix the bug in
devm_fwnode_get_index_gpiod_from_child(). Other callers would still need
to be reworked. The effort would be the same as with the chosen solution.

Signed-off-by: Georg Waibel <georg.waibel@sensor-technik.de>
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Waibel Georg and committed by
Mark Brown
025bf377 65d80db2

+13 -10
+1 -5
drivers/gpio/gpiolib.c
··· 4244 4244 * 4245 4245 * Returns: 4246 4246 * On successful request the GPIO pin is configured in accordance with 4247 - * provided @dflags. If the node does not have the requested GPIO 4248 - * property, NULL is returned. 4247 + * provided @dflags. 4249 4248 * 4250 4249 * In case of error an ERR_PTR() is returned. 4251 4250 */ ··· 4266 4267 index, &flags); 4267 4268 4268 4269 if (!desc || IS_ERR(desc)) { 4269 - /* If it is not there, just return NULL */ 4270 - if (PTR_ERR(desc) == -ENOENT) 4271 - return NULL; 4272 4270 return desc; 4273 4271 } 4274 4272
+2
drivers/regulator/da9211-regulator.c
··· 289 289 0, 290 290 GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, 291 291 "da9211-enable"); 292 + if (IS_ERR(pdata->gpiod_ren[n])) 293 + pdata->gpiod_ren[n] = NULL; 292 294 n++; 293 295 } 294 296
+3 -1
drivers/regulator/s2mps11.c
··· 843 843 0, 844 844 GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, 845 845 "s2mps11-regulator"); 846 - if (IS_ERR(gpio[reg])) { 846 + if (PTR_ERR(gpio[reg]) == -ENOENT) 847 + gpio[reg] = NULL; 848 + else if (IS_ERR(gpio[reg])) { 847 849 dev_err(&pdev->dev, "Failed to get control GPIO for %d/%s\n", 848 850 reg, rdata[reg].name); 849 851 continue;
+3 -1
drivers/regulator/s5m8767.c
··· 574 574 0, 575 575 GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE, 576 576 "s5m8767"); 577 - if (IS_ERR(rdata->ext_control_gpiod)) 577 + if (PTR_ERR(rdata->ext_control_gpiod) == -ENOENT) 578 + rdata->ext_control_gpiod = NULL; 579 + else if (IS_ERR(rdata->ext_control_gpiod)) 578 580 return PTR_ERR(rdata->ext_control_gpiod); 579 581 580 582 rdata->id = i;
+4 -3
drivers/regulator/tps65090-regulator.c
··· 371 371 "dcdc-ext-control-gpios", 0, 372 372 gflags, 373 373 "tps65090"); 374 - if (IS_ERR(rpdata->gpiod)) 375 - return ERR_CAST(rpdata->gpiod); 376 - if (!rpdata->gpiod) 374 + if (PTR_ERR(rpdata->gpiod) == -ENOENT) { 377 375 dev_err(&pdev->dev, 378 376 "could not find DCDC external control GPIO\n"); 377 + rpdata->gpiod = NULL; 378 + } else if (IS_ERR(rpdata->gpiod)) 379 + return ERR_CAST(rpdata->gpiod); 379 380 } 380 381 381 382 if (of_property_read_u32(tps65090_matches[idx].of_node,