diff options
| author | Kumar Kartikeya Dwivedi <memxor@gmail.com> | 2026-09-04 10:43:19 +0200 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-09-04 07:58:36 -0700 |
| commit | 6668ed271eaefaa63e686bdfbedaeb7b8e492722 (patch) | |
| tree | 58e8288fead484f6755ad0815fc74c3742663761 /drivers/gpio/gpio-tn48m.c | |
| download | linux-stable-6668ed271eaefaa63e686bdfbedaeb7b8e492722.tar.gz linux-stable-6668ed271eaefaa63e686bdfbedaeb7b8e492722.zip | |
selftests/bpf: Reject graph kptr use after RCU unlockgrafted
Add a sleepable verifier test that loads a graph-node local kptr in an
explicit RCU read-side critical section, then passes its node to
bpf_rbtree_remove() after the section ends.
Before the verifier fix, the stale NON_OWN_REF flag makes the node look like
a live borrowed reference and the program is accepted. After the fix, the
pointer is demoted without NON_OWN_REF and the graph kfunc argument is
rejected.
Also exercise a graph kptr loaded while a spin lock provides implicit RCU
protection. The pointer must be invalidated when the lock is released, which
guards the required ordering between non-owning-reference invalidation and
RCU demotion.
Update the existing fault-protected load test state description. The
post-unlock pointer no longer carries NON_OWN_REF, but remains readable
because the load is rewritten to use BPF_PROBE_MEM.
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20260904084325.52250-7-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'drivers/gpio/gpio-tn48m.c')
| -rw-r--r-- | drivers/gpio/gpio-tn48m.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-tn48m.c b/drivers/gpio/gpio-tn48m.c new file mode 100644 index 000000000..4fcd0bc24 --- /dev/null +++ b/drivers/gpio/gpio-tn48m.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Delta TN48M CPLD GPIO driver + * + * Copyright (C) 2021 Sartura Ltd. + * + * Author: Robert Marko <robert.marko@sartura.hr> + */ + +#include <linux/device.h> +#include <linux/gpio/driver.h> +#include <linux/gpio/regmap.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +enum tn48m_gpio_type { + TN48M_GP0 = 1, + TN48M_GPI, +}; + +struct tn48m_gpio_config { + int ngpio; + int ngpio_per_reg; + enum tn48m_gpio_type type; +}; + +static const struct tn48m_gpio_config tn48m_gpo_config = { + .ngpio = 4, + .ngpio_per_reg = 4, + .type = TN48M_GP0, +}; + +static const struct tn48m_gpio_config tn48m_gpi_config = { + .ngpio = 4, + .ngpio_per_reg = 4, + .type = TN48M_GPI, +}; + +static int tn48m_gpio_probe(struct platform_device *pdev) +{ + const struct tn48m_gpio_config *gpio_config; + struct gpio_regmap_config config = {}; + struct regmap *regmap; + u32 base; + int ret; + + if (!pdev->dev.parent) + return -ENODEV; + + gpio_config = device_get_match_data(&pdev->dev); + if (!gpio_config) + return -ENODEV; + + ret = device_property_read_u32(&pdev->dev, "reg", &base); + if (ret) + return ret; + + regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!regmap) + return -ENODEV; + + config.regmap = regmap; + config.parent = &pdev->dev; + config.ngpio = gpio_config->ngpio; + config.ngpio_per_reg = gpio_config->ngpio_per_reg; + switch (gpio_config->type) { + case TN48M_GP0: + config.reg_set_base = base; + break; + case TN48M_GPI: + config.reg_dat_base = base; + break; + default: + return -EINVAL; + } + + return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(&pdev->dev, &config)); +} + +static const struct of_device_id tn48m_gpio_of_match[] = { + { .compatible = "delta,tn48m-gpo", .data = &tn48m_gpo_config }, + { .compatible = "delta,tn48m-gpi", .data = &tn48m_gpi_config }, + { } +}; +MODULE_DEVICE_TABLE(of, tn48m_gpio_of_match); + +static struct platform_driver tn48m_gpio_driver = { + .driver = { + .name = "delta-tn48m-gpio", + .of_match_table = tn48m_gpio_of_match, + }, + .probe = tn48m_gpio_probe, +}; +module_platform_driver(tn48m_gpio_driver); + +MODULE_AUTHOR("Robert Marko <robert.marko@sartura.hr>"); +MODULE_DESCRIPTION("Delta TN48M CPLD GPIO driver"); +MODULE_LICENSE("GPL"); |
