From a8a08f667680fecf41ce1c9d54322f39f19dade9 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Mon, 19 May 2025 15:27:37 +0100 Subject: [PATCH] gpiolib: Avoid the hotplug performance reduction The 6.9 kernel introduced a large patchset [1] designed to make gpiochip usage safe in the presence of potential hotplugging events. The changes included protecting every gpiochip access with a claim of an interlock. Running on a Pi 5 these changes reduce GPIO performance from userspace by around 10%. The penalty would be proportionally higher from kernel, as seen by SPI speed reductions. Patch the gpiolib implementation to remove the protection of gpiochip accesses. By providing alternative implementations of the relevant macros, the changes are localised and therefore easier to verify. See: https://github.com/raspberrypi/linux/issues/6854 [1] https://lwn.net/Articles/960024/ Signed-off-by: Phil Elwell --- drivers/gpio/gpiolib.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c0387fca533abb..b0b97cb8cd6247 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -53,6 +53,42 @@ #define dont_test_bit(b,d) (0) +#define REJECT_HOTPLUG_TAX 1 + +#if REJECT_HOTPLUG_TAX + +#undef srcu_dereference +#define srcu_dereference(obj, srcu) obj + +#undef srcu_dereference_check +#define srcu_dereference_check(obj, srcu, held) obj + +#undef guard +#define guard(srcu) (void) + +#undef scoped_guard +#define scoped_guard(x, y) +#undef list_for_each_entry_srcu +#define list_for_each_entry_srcu(pos, head, member, srcu) \ + list_for_each_entry(pos, head, member) + +#undef CLASS +#define CLASS(gcg, gd) \ + struct gcg gd = gcg ## _init + +static struct gpio_chip_guard gpio_chip_guard_init(struct gpio_desc *desc) +{ + struct gpio_chip_guard _guard; + + _guard.gdev = desc->gdev; + _guard.idx = 0; + _guard.gc = _guard.gdev->chip; + + return _guard; +} + +#endif + /* Device and char device-related information */ static DEFINE_IDA(gpio_ida); static dev_t gpio_devt;