Input: adp5588-keys - switch to using managed resources
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 31 May 2022 21:07:39 +0000 (14:07 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 31 May 2022 21:09:41 +0000 (14:09 -0700)
This simplifies error handling in probe() and reduces amount of explicit
code in remove().

Acked-by: Michael Hennerich <michael.hennerich@analog.com>
Link: https://lore.kernel.org/r/20220528045631.289821-3-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/keyboard/adp5588-keys.c

index ac21873..1bd1ed6 100644 (file)
@@ -50,7 +50,6 @@ struct adp5588_kpad {
        unsigned short gpimapsize;
 #ifdef CONFIG_GPIOLIB
        unsigned char gpiomap[ADP5588_MAXGPIO];
-       bool export_gpio;
        struct gpio_chip gc;
        struct mutex gpio_lock; /* Protect cached dir, dat_out */
        u8 dat_out[3];
@@ -182,6 +181,21 @@ static int adp5588_build_gpiomap(struct adp5588_kpad *kpad,
        return n_unused;
 }
 
+static void adp5588_gpio_do_teardown(void *_kpad)
+{
+       struct adp5588_kpad *kpad = _kpad;
+       struct device *dev = &kpad->client->dev;
+       const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev);
+       const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
+       int error;
+
+       error = gpio_data->teardown(kpad->client,
+                                   kpad->gc.base, kpad->gc.ngpio,
+                                   gpio_data->context);
+       if (error)
+               dev_warn(&kpad->client->dev, "teardown failed %d\n", error);
+}
+
 static int adp5588_gpio_add(struct adp5588_kpad *kpad)
 {
        struct device *dev = &kpad->client->dev;
@@ -198,8 +212,6 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
                return 0;
        }
 
-       kpad->export_gpio = true;
-
        kpad->gc.direction_input = adp5588_gpio_direction_input;
        kpad->gc.direction_output = adp5588_gpio_direction_output;
        kpad->gc.get = adp5588_gpio_get_value;
@@ -213,9 +225,9 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
 
        mutex_init(&kpad->gpio_lock);
 
-       error = gpiochip_add_data(&kpad->gc, kpad);
+       error = devm_gpiochip_add_data(dev, &kpad->gc, kpad);
        if (error) {
-               dev_err(dev, "gpiochip_add failed, err: %d\n", error);
+               dev_err(dev, "gpiochip_add failed: %d\n", error);
                return error;
        }
 
@@ -230,41 +242,24 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad)
                                         kpad->gc.base, kpad->gc.ngpio,
                                         gpio_data->context);
                if (error)
-                       dev_warn(dev, "setup failed, %d\n", error);
+                       dev_warn(dev, "setup failed: %d\n", error);
        }
 
-       return 0;
-}
-
-static void adp5588_gpio_remove(struct adp5588_kpad *kpad)
-{
-       struct device *dev = &kpad->client->dev;
-       const struct adp5588_kpad_platform_data *pdata = dev_get_platdata(dev);
-       const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data;
-       int error;
-
-       if (!kpad->export_gpio)
-               return;
-
        if (gpio_data->teardown) {
-               error = gpio_data->teardown(kpad->client,
-                                           kpad->gc.base, kpad->gc.ngpio,
-                                           gpio_data->context);
+               error = devm_add_action(dev, adp5588_gpio_do_teardown, kpad);
                if (error)
-                       dev_warn(dev, "teardown failed %d\n", error);
+                       dev_warn(dev, "failed to schedule teardown: %d\n",
+                                error);
        }
 
-       gpiochip_remove(&kpad->gc);
+       return 0;
 }
+
 #else
 static inline int adp5588_gpio_add(struct adp5588_kpad *kpad)
 {
        return 0;
 }
-
-static inline void adp5588_gpio_remove(struct adp5588_kpad *kpad)
-{
-}
 #endif
 
 static void adp5588_report_events(struct adp5588_kpad *kpad, int ev_cnt)
@@ -510,21 +505,20 @@ static int adp5588_probe(struct i2c_client *client,
                return -EINVAL;
        }
 
-       kpad = kzalloc(sizeof(*kpad), GFP_KERNEL);
-       input = input_allocate_device();
-       if (!kpad || !input) {
-               error = -ENOMEM;
-               goto err_free_mem;
-       }
+       kpad = devm_kzalloc(&client->dev, sizeof(*kpad), GFP_KERNEL);
+       if (!kpad)
+               return -ENOMEM;
+
+       input = devm_input_allocate_device(&client->dev);
+       if (!input)
+               return -ENOMEM;
 
        kpad->client = client;
        kpad->input = input;
 
        ret = adp5588_read(client, DEV_ID);
-       if (ret < 0) {
-               error = ret;
-               goto err_free_mem;
-       }
+       if (ret < 0)
+               return ret;
 
        revid = (u8) ret & ADP5588_DEVICE_ID_MASK;
        if (WA_DELAYED_READOUT_REVID(revid))
@@ -532,7 +526,6 @@ static int adp5588_probe(struct i2c_client *client,
 
        input->name = client->name;
        input->phys = "adp5588-keys/input0";
-       input->dev.parent = &client->dev;
 
        input_set_drvdata(input, kpad);
 
@@ -569,58 +562,43 @@ static int adp5588_probe(struct i2c_client *client,
 
        error = input_register_device(input);
        if (error) {
-               dev_err(&client->dev, "unable to register input device\n");
-               goto err_free_mem;
+               dev_err(&client->dev, "unable to register input device: %d\n",
+                       error);
+               return error;
        }
 
-       error = request_threaded_irq(client->irq,
-                                    adp5588_hard_irq, adp5588_thread_irq,
-                                    IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                                    client->dev.driver->name, kpad);
+       error = devm_request_threaded_irq(&client->dev, client->irq,
+                                         adp5588_hard_irq, adp5588_thread_irq,
+                                         IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                         client->dev.driver->name, kpad);
        if (error) {
-               dev_err(&client->dev, "irq %d busy?\n", client->irq);
-               goto err_unreg_dev;
+               dev_err(&client->dev, "failed to request irq %d: %d\n",
+                       client->irq, error);
+               return error;
        }
 
        error = adp5588_setup(client);
        if (error)
-               goto err_free_irq;
+               return error;
 
        if (kpad->gpimapsize)
                adp5588_report_switch_state(kpad);
 
        error = adp5588_gpio_add(kpad);
        if (error)
-               goto err_free_irq;
+               return error;
 
        device_init_wakeup(&client->dev, 1);
-       i2c_set_clientdata(client, kpad);
 
        dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
        return 0;
-
- err_free_irq:
-       free_irq(client->irq, kpad);
- err_unreg_dev:
-       input_unregister_device(input);
-       input = NULL;
- err_free_mem:
-       input_free_device(input);
-       kfree(kpad);
-
-       return error;
 }
 
 static int adp5588_remove(struct i2c_client *client)
 {
-       struct adp5588_kpad *kpad = i2c_get_clientdata(client);
-
        adp5588_write(client, CFG, 0);
-       free_irq(client->irq, kpad);
-       input_unregister_device(kpad->input);
-       adp5588_gpio_remove(kpad);
-       kfree(kpad);
 
+       /* all resources will be freed by devm */
        return 0;
 }