]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
gpio: shared: don't allocate the lookup table until we really need it
authorBartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Tue, 6 Jan 2026 09:34:23 +0000 (10:34 +0100)
committerBartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Wed, 7 Jan 2026 08:31:14 +0000 (09:31 +0100)
We allocate memory for the GPIO lookup table at the top of
gpio_shared_add_proxy_lookup() but we don't use it until the very end.
Depending on the timing, we may return earlier. Move the allocation
towards the end.

Fixes: a060b8c511ab ("gpiolib: implement low-level, shared GPIO support")
Tested-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20260106-gpio-shared-fixes-v2-3-c7091d2f7581@oss.qualcomm.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
drivers/gpio/gpiolib-shared.c

index 4c57b0928760c3f9f251ca88cfc54ee5887d50c9..076d8642675c2723c8938cbd22b1b51014c23871 100644 (file)
@@ -443,14 +443,10 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id,
                                 unsigned long lflags)
 {
        const char *dev_id = dev_name(consumer);
+       struct gpiod_lookup_table *lookup;
        struct gpio_shared_entry *entry;
        struct gpio_shared_ref *ref;
 
-       struct gpiod_lookup_table *lookup __free(kfree) =
-                       kzalloc(struct_size(lookup, table, 2), GFP_KERNEL);
-       if (!lookup)
-               return -ENOMEM;
-
        list_for_each_entry(entry, &gpio_shared_list, list) {
                list_for_each_entry(ref, &entry->refs, list) {
                        guard(mutex)(&ref->lock);
@@ -482,6 +478,10 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id,
                        if (!key)
                                return -ENOMEM;
 
+                       lookup = kzalloc(struct_size(lookup, table, 2), GFP_KERNEL);
+                       if (!lookup)
+                               return -ENOMEM;
+
                        pr_debug("Adding machine lookup entry for a shared GPIO for consumer %s, with key '%s' and con_id '%s'\n",
                                 dev_id, key, ref->con_id ?: "none");
 
@@ -489,7 +489,7 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id,
                        lookup->table[0] = GPIO_LOOKUP(no_free_ptr(key), 0,
                                                       ref->con_id, lflags);
 
-                       ref->lookup = no_free_ptr(lookup);
+                       ref->lookup = lookup;
                        gpiod_add_lookup_table(ref->lookup);
 
                        return 0;