]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
gpio: cdev: convert lineevent_create() and linereq_create() to FD_PREPARE()
authorKent Gibson <warthog618@gmail.com>
Mon, 16 Feb 2026 12:37:09 +0000 (20:37 +0800)
committerBartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Mon, 23 Feb 2026 09:39:07 +0000 (10:39 +0100)
linehandle_create() was recently converted to use FD_PREPARE() to
simplify fd creation and cleanup logic.
Apply the equivalent conversion to lineevent_create() and
linereq_create().

Signed-off-by: Kent Gibson <warthog618@gmail.com>
Link: https://patch.msgid.link/20260216123709.281444-1-warthog618@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
drivers/gpio/gpiolib-cdev.c

index 73ae77f0f2133fad2c38b21dc18cc24361050f99..c919ec0d0a660a44c0f8e705813c623bc2c1c54b 100644 (file)
@@ -1586,15 +1586,16 @@ static const struct file_operations line_fileops = {
 #endif
 };
 
+DEFINE_FREE(linereq_free, struct linereq *, if (!IS_ERR_OR_NULL(_T)) linereq_free(_T))
+
 static int linereq_create(struct gpio_device *gdev, void __user *ip)
 {
        struct gpio_v2_line_request ulr;
        struct gpio_v2_line_config *lc;
-       struct linereq *lr;
-       struct file *file;
+       struct linereq *lr __free(linereq_free) = NULL;
        u64 flags, edflags;
        unsigned int i;
-       int fd, ret;
+       int ret;
 
        if (copy_from_user(&ulr, ip, sizeof(ulr)))
                return -EFAULT;
@@ -1627,10 +1628,8 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
                /* label is only initialized if consumer is set */
                lr->label = kstrndup(ulr.consumer, sizeof(ulr.consumer) - 1,
                                     GFP_KERNEL);
-               if (!lr->label) {
-                       ret = -ENOMEM;
-                       goto out_free_linereq;
-               }
+               if (!lr->label)
+                       return -ENOMEM;
        }
 
        mutex_init(&lr->config_mutex);
@@ -1649,14 +1648,12 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
                u32 offset = ulr.offsets[i];
                struct gpio_desc *desc = gpio_device_get_desc(gdev, offset);
 
-               if (IS_ERR(desc)) {
-                       ret = PTR_ERR(desc);
-                       goto out_free_linereq;
-               }
+               if (IS_ERR(desc))
+                       return PTR_ERR(desc);
 
                ret = gpiod_request_user(desc, lr->label);
                if (ret)
-                       goto out_free_linereq;
+                       return ret;
 
                lr->lines[i].desc = desc;
                flags = gpio_v2_line_config_flags(lc, i);
@@ -1664,7 +1661,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
 
                ret = gpiod_set_transitory(desc, false);
                if (ret < 0)
-                       goto out_free_linereq;
+                       return ret;
 
                edflags = flags & GPIO_V2_LINE_EDGE_DETECTOR_FLAGS;
                /*
@@ -1676,16 +1673,16 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
 
                        ret = gpiod_direction_output_nonotify(desc, val);
                        if (ret)
-                               goto out_free_linereq;
+                               return ret;
                } else if (flags & GPIO_V2_LINE_FLAG_INPUT) {
                        ret = gpiod_direction_input_nonotify(desc);
                        if (ret)
-                               goto out_free_linereq;
+                               return ret;
 
                        ret = edge_detector_setup(&lr->lines[i], lc, i,
                                                  edflags);
                        if (ret)
-                               goto out_free_linereq;
+                               return ret;
                }
 
                lr->lines[i].edflags = edflags;
@@ -1700,44 +1697,25 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
        ret = blocking_notifier_chain_register(&gdev->device_notifier,
                                               &lr->device_unregistered_nb);
        if (ret)
-               goto out_free_linereq;
-
-       fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
-       if (fd < 0) {
-               ret = fd;
-               goto out_free_linereq;
-       }
+               return ret;
 
-       file = anon_inode_getfile("gpio-line", &line_fileops, lr,
-                                 O_RDONLY | O_CLOEXEC);
-       if (IS_ERR(file)) {
-               ret = PTR_ERR(file);
-               goto out_put_unused_fd;
-       }
+       FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC,
+                  anon_inode_getfile("gpio-line", &line_fileops, lr,
+                                     O_RDONLY | O_CLOEXEC));
+       if (fdf.err)
+               return fdf.err;
+       retain_and_null_ptr(lr);
 
-       ulr.fd = fd;
-       if (copy_to_user(ip, &ulr, sizeof(ulr))) {
-               /*
-                * fput() will trigger the release() callback, so do not go onto
-                * the regular error cleanup path here.
-                */
-               fput(file);
-               put_unused_fd(fd);
+       ulr.fd = fd_prepare_fd(fdf);
+       if (copy_to_user(ip, &ulr, sizeof(ulr)))
                return -EFAULT;
-       }
 
-       fd_install(fd, file);
+       fd_publish(fdf);
 
        dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
-               lr->num_lines);
+               ulr.num_lines);
 
        return 0;
-
-out_put_unused_fd:
-       put_unused_fd(fd);
-out_free_linereq:
-       linereq_free(lr);
-       return ret;
 }
 
 #ifdef CONFIG_GPIO_CDEV_V1
@@ -2010,16 +1988,16 @@ static irqreturn_t lineevent_irq_handler(int irq, void *p)
        return IRQ_WAKE_THREAD;
 }
 
+DEFINE_FREE(lineevent_free, struct lineevent_state *, if (!IS_ERR_OR_NULL(_T)) lineevent_free(_T))
+
 static int lineevent_create(struct gpio_device *gdev, void __user *ip)
 {
        struct gpioevent_request eventreq;
-       struct lineevent_state *le;
+       struct lineevent_state *le __free(lineevent_free) = NULL;
        struct gpio_desc *desc;
-       struct file *file;
        u32 offset;
        u32 lflags;
        u32 eflags;
-       int fd;
        int ret;
        int irq, irqflags = 0;
        char *label;
@@ -2064,15 +2042,13 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
                le->label = kstrndup(eventreq.consumer_label,
                                     sizeof(eventreq.consumer_label) - 1,
                                     GFP_KERNEL);
-               if (!le->label) {
-                       ret = -ENOMEM;
-                       goto out_free_le;
-               }
+               if (!le->label)
+                       return -ENOMEM;
        }
 
        ret = gpiod_request_user(desc, le->label);
        if (ret)
-               goto out_free_le;
+               return ret;
        le->desc = desc;
        le->eflags = eflags;
 
@@ -2080,15 +2056,13 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
 
        ret = gpiod_direction_input(desc);
        if (ret)
-               goto out_free_le;
+               return ret;
 
        gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED);
 
        irq = gpiod_to_irq(desc);
-       if (irq <= 0) {
-               ret = -ENODEV;
-               goto out_free_le;
-       }
+       if (irq <= 0)
+               return -ENODEV;
 
        if (eflags & GPIOEVENT_REQUEST_RISING_EDGE)
                irqflags |= test_bit(GPIOD_FLAG_ACTIVE_LOW, &desc->flags) ?
@@ -2105,13 +2079,11 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
        ret = blocking_notifier_chain_register(&gdev->device_notifier,
                                               &le->device_unregistered_nb);
        if (ret)
-               goto out_free_le;
+               return ret;
 
        label = make_irq_label(le->label);
-       if (IS_ERR(label)) {
-               ret = PTR_ERR(label);
-               goto out_free_le;
-       }
+       if (IS_ERR(label))
+               return PTR_ERR(label);
 
        /* Request a thread to read the events */
        ret = request_threaded_irq(irq,
@@ -2122,46 +2094,25 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
                                   le);
        if (ret) {
                free_irq_label(label);
-               goto out_free_le;
+               return ret;
        }
 
        le->irq = irq;
 
-       fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
-       if (fd < 0) {
-               ret = fd;
-               goto out_free_le;
-       }
-
-       file = anon_inode_getfile("gpio-event",
-                                 &lineevent_fileops,
-                                 le,
-                                 O_RDONLY | O_CLOEXEC);
-       if (IS_ERR(file)) {
-               ret = PTR_ERR(file);
-               goto out_put_unused_fd;
-       }
+       FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC,
+                  anon_inode_getfile("gpio-event", &lineevent_fileops, le,
+                                     O_RDONLY | O_CLOEXEC));
+       if (fdf.err)
+               return fdf.err;
+       retain_and_null_ptr(le);
 
-       eventreq.fd = fd;
-       if (copy_to_user(ip, &eventreq, sizeof(eventreq))) {
-               /*
-                * fput() will trigger the release() callback, so do not go onto
-                * the regular error cleanup path here.
-                */
-               fput(file);
-               put_unused_fd(fd);
+       eventreq.fd = fd_prepare_fd(fdf);
+       if (copy_to_user(ip, &eventreq, sizeof(eventreq)))
                return -EFAULT;
-       }
 
-       fd_install(fd, file);
+       fd_publish(fdf);
 
        return 0;
-
-out_put_unused_fd:
-       put_unused_fd(fd);
-out_free_le:
-       lineevent_free(le);
-       return ret;
 }
 
 static void gpio_v2_line_info_to_v1(struct gpio_v2_line_info *info_v2,