From: Bartosz Golaszewski <bgolaszewski@xxxxxxxxxxxx> As a preparation for implementing dynamically created dummy GPIO chips: drop the limit on the number of chips. Let's use a linked list to store the chip context structures. Let's rename gpio_mockup_unregister_pdevs() to gpio_mockup_unregister_devices() as we're now handling structures in which struct platform_device is embedded instead of operating on platform devices directly. Note: this does not remove the limit on the number of ranges passed as a module parameter. For now nothing changes in how the module works for user-space. This patch will however allow us to create a higher number of chips once we can do this dynamically. Signed-off-by: Bartosz Golaszewski <bgolaszewski@xxxxxxxxxxxx> --- drivers/gpio/gpio-mockup.c | 59 ++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 19c092f814fd..801fba6496a4 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -13,6 +13,7 @@ #include <linux/irq.h> #include <linux/irq_sim.h> #include <linux/irqdomain.h> +#include <linux/list.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/property.h> @@ -24,12 +25,11 @@ #undef pr_fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define GPIO_MOCKUP_MAX_GC 10 /* * We're storing two values per chip: the GPIO base and the number * of GPIO lines. */ -#define GPIO_MOCKUP_MAX_RANGES (GPIO_MOCKUP_MAX_GC * 2) +#define GPIO_MOCKUP_MAX_RANGES (10 * 2) /* Maximum of three properties + the sentinel. */ #define GPIO_MOCKUP_MAX_PROP 4 @@ -505,27 +505,37 @@ static struct platform_driver gpio_mockup_driver = { .probe = gpio_mockup_probe, }; -static struct platform_device *gpio_mockup_pdevs[GPIO_MOCKUP_MAX_GC]; +struct gpio_mockup_device { + struct list_head list; + struct platform_device *pdev; +}; -static void gpio_mockup_unregister_pdevs(void) +static LIST_HEAD(gpio_mockup_devices); + +static void gpio_mockup_unregister_one_device(struct gpio_mockup_device *dev) { - struct platform_device *pdev; - int i; + list_del(&dev->list); + platform_device_unregister(dev->pdev); + kfree(dev); +} - for (i = 0; i < GPIO_MOCKUP_MAX_GC; i++) { - pdev = gpio_mockup_pdevs[i]; +static void gpio_mockup_unregister_devices(void) +{ + struct gpio_mockup_device *mockup_dev; + struct list_head *curr, *next; - if (pdev) - platform_device_unregister(pdev); + list_for_each_safe(curr, next, &gpio_mockup_devices) { + mockup_dev = list_entry(curr, struct gpio_mockup_device, list); + gpio_mockup_unregister_one_device(mockup_dev); } } static int __init gpio_mockup_init(void) { struct property_entry properties[GPIO_MOCKUP_MAX_PROP]; + struct gpio_mockup_device *mockup_dev; int i, prop, num_chips, err = 0, base; struct platform_device_info pdevinfo; - struct platform_device *pdev; u16 ngpio; if ((gpio_mockup_num_ranges < 2) || @@ -576,26 +586,37 @@ static int __init gpio_mockup_init(void) pdevinfo.id = i; pdevinfo.properties = properties; - pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) { + mockup_dev = kzalloc(sizeof(*mockup_dev), GFP_KERNEL); + if (!mockup_dev) { + err = -ENOMEM; + goto err_out; + } + + mockup_dev->pdev = platform_device_register_full(&pdevinfo); + if (IS_ERR(mockup_dev->pdev)) { pr_err("error registering device"); - platform_driver_unregister(&gpio_mockup_driver); - gpio_mockup_unregister_pdevs(); - debugfs_remove_recursive(gpio_mockup_dbg_dir); - return PTR_ERR(pdev); + kfree(mockup_dev); + err = PTR_ERR(mockup_dev->pdev); + goto err_out; } - gpio_mockup_pdevs[i] = pdev; + list_add(&mockup_dev->list, &gpio_mockup_devices); } return 0; + +err_out: + platform_driver_unregister(&gpio_mockup_driver); + gpio_mockup_unregister_devices(); + debugfs_remove_recursive(gpio_mockup_dbg_dir); + return err; } static void __exit gpio_mockup_exit(void) { debugfs_remove_recursive(gpio_mockup_dbg_dir); platform_driver_unregister(&gpio_mockup_driver); - gpio_mockup_unregister_pdevs(); + gpio_mockup_unregister_devices(); } module_init(gpio_mockup_init); -- 2.26.1