gpio: aggregator: reorder functions to prepare for configfs introduction
authorKoichiro Den <koichiro.den@canonical.com>
Mon, 7 Apr 2025 04:30:11 +0000 (13:30 +0900)
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Wed, 9 Apr 2025 13:48:49 +0000 (15:48 +0200)
Reorder functions in drivers/gpio/gpio-aggregator.c to prepare for the
configfs-based interface additions in subsequent commits. Arrange the
code so that the configfs implementations will appear above the existing
sysfs-specific code, since the latter will partly depend on the configfs
interface implementations when it starts to expose the settings to
configfs.

The order in drivers/gpio/gpio-aggregator.c will be as follows:

* Basic gpio_aggregator/gpio_aggregator_line representations
* Common utility functions
* GPIO Forwarder implementations
* Configfs interface implementations
* Sysfs interface implementations
* Platform device implementations
* Module init/exit implementations

This separate commit ensures a clean diff for the subsequent commits.

No functional change.

Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
Link: https://lore.kernel.org/r/20250407043019.4105613-2-koichiro.den@canonical.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
drivers/gpio/gpio-aggregator.c

index d232ea865356dfae8a6df50591185969175bd076..e026deb4ac64c0c07d638ddf3006d529c8422e4e 100644 (file)
@@ -61,194 +61,6 @@ static int aggr_add_gpio(struct gpio_aggregator *aggr, const char *key,
        return 0;
 }
 
-static int aggr_parse(struct gpio_aggregator *aggr)
-{
-       char *args = skip_spaces(aggr->args);
-       char *name, *offsets, *p;
-       unsigned int i, n = 0;
-       int error = 0;
-
-       unsigned long *bitmap __free(bitmap) =
-                       bitmap_alloc(AGGREGATOR_MAX_GPIOS, GFP_KERNEL);
-       if (!bitmap)
-               return -ENOMEM;
-
-       args = next_arg(args, &name, &p);
-       while (*args) {
-               args = next_arg(args, &offsets, &p);
-
-               p = get_options(offsets, 0, &error);
-               if (error == 0 || *p) {
-                       /* Named GPIO line */
-                       error = aggr_add_gpio(aggr, name, U16_MAX, &n);
-                       if (error)
-                               return error;
-
-                       name = offsets;
-                       continue;
-               }
-
-               /* GPIO chip + offset(s) */
-               error = bitmap_parselist(offsets, bitmap, AGGREGATOR_MAX_GPIOS);
-               if (error) {
-                       pr_err("Cannot parse %s: %d\n", offsets, error);
-                       return error;
-               }
-
-               for_each_set_bit(i, bitmap, AGGREGATOR_MAX_GPIOS) {
-                       error = aggr_add_gpio(aggr, name, i, &n);
-                       if (error)
-                               return error;
-               }
-
-               args = next_arg(args, &name, &p);
-       }
-
-       if (!n) {
-               pr_err("No GPIOs specified\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static ssize_t new_device_store(struct device_driver *driver, const char *buf,
-                               size_t count)
-{
-       struct gpio_aggregator *aggr;
-       struct platform_device *pdev;
-       int res, id;
-
-       if (!try_module_get(THIS_MODULE))
-               return -ENOENT;
-
-       /* kernfs guarantees string termination, so count + 1 is safe */
-       aggr = kzalloc(sizeof(*aggr) + count + 1, GFP_KERNEL);
-       if (!aggr) {
-               res = -ENOMEM;
-               goto put_module;
-       }
-
-       memcpy(aggr->args, buf, count + 1);
-
-       aggr->lookups = kzalloc(struct_size(aggr->lookups, table, 1),
-                               GFP_KERNEL);
-       if (!aggr->lookups) {
-               res = -ENOMEM;
-               goto free_ga;
-       }
-
-       mutex_lock(&gpio_aggregator_lock);
-       id = idr_alloc(&gpio_aggregator_idr, aggr, 0, 0, GFP_KERNEL);
-       mutex_unlock(&gpio_aggregator_lock);
-
-       if (id < 0) {
-               res = id;
-               goto free_table;
-       }
-
-       aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, id);
-       if (!aggr->lookups->dev_id) {
-               res = -ENOMEM;
-               goto remove_idr;
-       }
-
-       res = aggr_parse(aggr);
-       if (res)
-               goto free_dev_id;
-
-       gpiod_add_lookup_table(aggr->lookups);
-
-       pdev = platform_device_register_simple(DRV_NAME, id, NULL, 0);
-       if (IS_ERR(pdev)) {
-               res = PTR_ERR(pdev);
-               goto remove_table;
-       }
-
-       aggr->pdev = pdev;
-       module_put(THIS_MODULE);
-       return count;
-
-remove_table:
-       gpiod_remove_lookup_table(aggr->lookups);
-free_dev_id:
-       kfree(aggr->lookups->dev_id);
-remove_idr:
-       mutex_lock(&gpio_aggregator_lock);
-       idr_remove(&gpio_aggregator_idr, id);
-       mutex_unlock(&gpio_aggregator_lock);
-free_table:
-       kfree(aggr->lookups);
-free_ga:
-       kfree(aggr);
-put_module:
-       module_put(THIS_MODULE);
-       return res;
-}
-
-static DRIVER_ATTR_WO(new_device);
-
-static void gpio_aggregator_free(struct gpio_aggregator *aggr)
-{
-       platform_device_unregister(aggr->pdev);
-       gpiod_remove_lookup_table(aggr->lookups);
-       kfree(aggr->lookups->dev_id);
-       kfree(aggr->lookups);
-       kfree(aggr);
-}
-
-static ssize_t delete_device_store(struct device_driver *driver,
-                                  const char *buf, size_t count)
-{
-       struct gpio_aggregator *aggr;
-       unsigned int id;
-       int error;
-
-       if (!str_has_prefix(buf, DRV_NAME "."))
-               return -EINVAL;
-
-       error = kstrtouint(buf + strlen(DRV_NAME "."), 10, &id);
-       if (error)
-               return error;
-
-       if (!try_module_get(THIS_MODULE))
-               return -ENOENT;
-
-       mutex_lock(&gpio_aggregator_lock);
-       aggr = idr_remove(&gpio_aggregator_idr, id);
-       mutex_unlock(&gpio_aggregator_lock);
-       if (!aggr) {
-               module_put(THIS_MODULE);
-               return -ENOENT;
-       }
-
-       gpio_aggregator_free(aggr);
-       module_put(THIS_MODULE);
-       return count;
-}
-static DRIVER_ATTR_WO(delete_device);
-
-static struct attribute *gpio_aggregator_attrs[] = {
-       &driver_attr_new_device.attr,
-       &driver_attr_delete_device.attr,
-       NULL
-};
-ATTRIBUTE_GROUPS(gpio_aggregator);
-
-static int __exit gpio_aggregator_idr_remove(int id, void *p, void *data)
-{
-       gpio_aggregator_free(p);
-       return 0;
-}
-
-static void __exit gpio_aggregator_remove_all(void)
-{
-       mutex_lock(&gpio_aggregator_lock);
-       idr_for_each(&gpio_aggregator_idr, gpio_aggregator_idr_remove, NULL);
-       idr_destroy(&gpio_aggregator_idr);
-       mutex_unlock(&gpio_aggregator_lock);
-}
-
 
 /*
  *  GPIO Forwarder
@@ -583,6 +395,184 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev,
 }
 
 
+/*
+ * Sysfs interface
+ */
+static int aggr_parse(struct gpio_aggregator *aggr)
+{
+       char *args = skip_spaces(aggr->args);
+       char *name, *offsets, *p;
+       unsigned int i, n = 0;
+       int error = 0;
+
+       unsigned long *bitmap __free(bitmap) =
+                       bitmap_alloc(AGGREGATOR_MAX_GPIOS, GFP_KERNEL);
+       if (!bitmap)
+               return -ENOMEM;
+
+       args = next_arg(args, &name, &p);
+       while (*args) {
+               args = next_arg(args, &offsets, &p);
+
+               p = get_options(offsets, 0, &error);
+               if (error == 0 || *p) {
+                       /* Named GPIO line */
+                       error = aggr_add_gpio(aggr, name, U16_MAX, &n);
+                       if (error)
+                               return error;
+
+                       name = offsets;
+                       continue;
+               }
+
+               /* GPIO chip + offset(s) */
+               error = bitmap_parselist(offsets, bitmap, AGGREGATOR_MAX_GPIOS);
+               if (error) {
+                       pr_err("Cannot parse %s: %d\n", offsets, error);
+                       return error;
+               }
+
+               for_each_set_bit(i, bitmap, AGGREGATOR_MAX_GPIOS) {
+                       error = aggr_add_gpio(aggr, name, i, &n);
+                       if (error)
+                               return error;
+               }
+
+               args = next_arg(args, &name, &p);
+       }
+
+       if (!n) {
+               pr_err("No GPIOs specified\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static ssize_t new_device_store(struct device_driver *driver, const char *buf,
+                               size_t count)
+{
+       struct gpio_aggregator *aggr;
+       struct platform_device *pdev;
+       int res, id;
+
+       if (!try_module_get(THIS_MODULE))
+               return -ENOENT;
+
+       /* kernfs guarantees string termination, so count + 1 is safe */
+       aggr = kzalloc(sizeof(*aggr) + count + 1, GFP_KERNEL);
+       if (!aggr) {
+               res = -ENOMEM;
+               goto put_module;
+       }
+
+       memcpy(aggr->args, buf, count + 1);
+
+       aggr->lookups = kzalloc(struct_size(aggr->lookups, table, 1),
+                               GFP_KERNEL);
+       if (!aggr->lookups) {
+               res = -ENOMEM;
+               goto free_ga;
+       }
+
+       mutex_lock(&gpio_aggregator_lock);
+       id = idr_alloc(&gpio_aggregator_idr, aggr, 0, 0, GFP_KERNEL);
+       mutex_unlock(&gpio_aggregator_lock);
+
+       if (id < 0) {
+               res = id;
+               goto free_table;
+       }
+
+       aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, id);
+       if (!aggr->lookups->dev_id) {
+               res = -ENOMEM;
+               goto remove_idr;
+       }
+
+       res = aggr_parse(aggr);
+       if (res)
+               goto free_dev_id;
+
+       gpiod_add_lookup_table(aggr->lookups);
+
+       pdev = platform_device_register_simple(DRV_NAME, id, NULL, 0);
+       if (IS_ERR(pdev)) {
+               res = PTR_ERR(pdev);
+               goto remove_table;
+       }
+
+       aggr->pdev = pdev;
+       module_put(THIS_MODULE);
+       return count;
+
+remove_table:
+       gpiod_remove_lookup_table(aggr->lookups);
+free_dev_id:
+       kfree(aggr->lookups->dev_id);
+remove_idr:
+       mutex_lock(&gpio_aggregator_lock);
+       idr_remove(&gpio_aggregator_idr, id);
+       mutex_unlock(&gpio_aggregator_lock);
+free_table:
+       kfree(aggr->lookups);
+free_ga:
+       kfree(aggr);
+put_module:
+       module_put(THIS_MODULE);
+       return res;
+}
+
+static DRIVER_ATTR_WO(new_device);
+
+static void gpio_aggregator_free(struct gpio_aggregator *aggr)
+{
+       platform_device_unregister(aggr->pdev);
+       gpiod_remove_lookup_table(aggr->lookups);
+       kfree(aggr->lookups->dev_id);
+       kfree(aggr->lookups);
+       kfree(aggr);
+}
+
+static ssize_t delete_device_store(struct device_driver *driver,
+                                  const char *buf, size_t count)
+{
+       struct gpio_aggregator *aggr;
+       unsigned int id;
+       int error;
+
+       if (!str_has_prefix(buf, DRV_NAME "."))
+               return -EINVAL;
+
+       error = kstrtouint(buf + strlen(DRV_NAME "."), 10, &id);
+       if (error)
+               return error;
+
+       if (!try_module_get(THIS_MODULE))
+               return -ENOENT;
+
+       mutex_lock(&gpio_aggregator_lock);
+       aggr = idr_remove(&gpio_aggregator_idr, id);
+       mutex_unlock(&gpio_aggregator_lock);
+       if (!aggr) {
+               module_put(THIS_MODULE);
+               return -ENOENT;
+       }
+
+       gpio_aggregator_free(aggr);
+       module_put(THIS_MODULE);
+       return count;
+}
+static DRIVER_ATTR_WO(delete_device);
+
+static struct attribute *gpio_aggregator_attrs[] = {
+       &driver_attr_new_device.attr,
+       &driver_attr_delete_device.attr,
+       NULL
+};
+ATTRIBUTE_GROUPS(gpio_aggregator);
+
+
 /*
  *  GPIO Aggregator platform device
  */
@@ -640,6 +630,20 @@ static struct platform_driver gpio_aggregator_driver = {
        },
 };
 
+static int __exit gpio_aggregator_idr_remove(int id, void *p, void *data)
+{
+       gpio_aggregator_free(p);
+       return 0;
+}
+
+static void __exit gpio_aggregator_remove_all(void)
+{
+       mutex_lock(&gpio_aggregator_lock);
+       idr_for_each(&gpio_aggregator_idr, gpio_aggregator_idr_remove, NULL);
+       idr_destroy(&gpio_aggregator_idr);
+       mutex_unlock(&gpio_aggregator_lock);
+}
+
 static int __init gpio_aggregator_init(void)
 {
        return platform_driver_register(&gpio_aggregator_driver);