gpio-delay had no sandbox coverage, which is how two bugs in it went unnoticed: gpio_delay_xlate() never propagated the requested index into the descriptor offset, so every consumer past the first silently collided with the first consumer's already-claimed offset 0; and the claimed/name tracking arrays were sized and bounds-checked against a hardcoded 32 instead of the driver's actual GPIO count. Both are fixed by a companion series that is a dependency of this patch: applied without it, this test fails outright, since it directly exercises both fixes.
Add a test requesting both consumers wired up by gpio-delay-test in test.dts (gpio_a 9 and 18): a third consumer colliding with an already-claimed offset must fail with -EBUSY, each consumer's write must land on its own wrapped GPIO line, and a request past the wrapped GPIO count must fail with -EINVAL rather than succeed against a hardcoded bound of 32. Gated on CONFIG_GPIO_DELAY, since not every sandbox variant that builds test/dm/gpio.c enables it (sandbox_vpl, sandbox_spl, sandbox_noinst, sandbox_flattree). Signed-off-by: Pranav Sanwal <[email protected]> --- test/dm/gpio.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/test/dm/gpio.c b/test/dm/gpio.c index b872dac9082..17a0dddf083 100644 --- a/test/dm/gpio.c +++ b/test/dm/gpio.c @@ -432,6 +432,75 @@ static int dm_test_gpio_get_dir_flags(struct unit_test_state *uts) } DM_TEST(dm_test_gpio_get_dir_flags, UTF_SCAN_PDATA | UTF_SCAN_FDT); +/* + * Test that gpio-delay correctly routes each consumer to its own wrapped + * real GPIO line. See gpio-delay-test in test.dts, which wraps gpio_a 9 + * and gpio_a 18. + */ +#if IS_ENABLED(CONFIG_GPIO_DELAY) +static int dm_test_gpio_delay(struct unit_test_state *uts) +{ + struct gpio_desc desc0, desc1, desc2, desc3; + struct udevice *dev, *gpio_a; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio_a)); + ut_asserteq_str("base-gpios", gpio_a->name); + + /* + * Requesting both consumers must succeed. Before the offset was + * propagated in gpio_delay_xlate(), both descriptors came back with + * offset 0, so this second request would fail with -EBUSY as it + * collided with the first consumer's already-claimed offset. + */ + ut_assertok(gpio_request_by_name(dev, "test6-gpios", 0, &desc0, 0)); + ut_assertok(gpio_request_by_name(dev, "test6-gpios", 1, &desc1, 0)); + + ut_asserteq_ptr(desc0.dev, desc1.dev); + ut_asserteq(0, desc0.offset); + ut_asserteq(1, desc1.offset); + + /* + * A third consumer mapped to the same offset as the first must be + * rejected as already requested. + */ + ut_asserteq(-EBUSY, gpio_request_by_name(dev, "test6-gpios", 2, &desc2, + 0)); + + /* + * Drive each consumer to a different level and confirm the write + * lands on its own wrapped real GPIO line, not the other one's. + * gpio_a has no set_value op of its own (it implements set_flags), + * so dm_gpio_set_value() routes through GPIOD_IS_OUT_ACTIVE. + */ + ut_assertok(dm_gpio_set_value(&desc0, 0)); + ut_assertok(dm_gpio_set_value(&desc1, 1)); + ut_asserteq(0, sandbox_gpio_get_flags(gpio_a, 9) & GPIOD_IS_OUT_ACTIVE); + ut_asserteq(GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(gpio_a, 18) & GPIOD_IS_OUT_ACTIVE); + + ut_assertok(dm_gpio_set_value(&desc0, 1)); + ut_assertok(dm_gpio_set_value(&desc1, 0)); + ut_asserteq(GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(gpio_a, 9) & GPIOD_IS_OUT_ACTIVE); + ut_asserteq(0, sandbox_gpio_get_flags(gpio_a, 18) & GPIOD_IS_OUT_ACTIVE); + + ut_assertok(dm_gpio_free(dev, &desc0)); + ut_assertok(dm_gpio_free(dev, &desc1)); + + /* + * An index beyond the wrapped GPIO count (2 here) must be rejected. + * Before gpio_count was set from the "gpios" property, this bound + * was checked against a hardcoded 32 and would have been let through. + */ + ut_asserteq(-EINVAL, gpio_request_by_name(dev, "test7-gpios", 0, &desc3, + 0)); + + return 0; +} +DM_TEST(dm_test_gpio_delay, UTF_SCAN_PDATA | UTF_SCAN_FDT); +#endif /* CONFIG_GPIO_DELAY */ + /* Test of gpio_get_acpi() */ static int dm_test_gpio_get_acpi(struct unit_test_state *uts) { -- 2.43.7
