gpio: cdev: convert lineevent_create() and linereq_create() to FD_PREPARE()

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>
This commit is contained in:
Kent Gibson 2026-02-16 20:37:09 +08:00 committed by Bartosz Golaszewski
parent 2c46f19c9a
commit 96c02c906a

View 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;
return ret;
fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
if (fd < 0) {
ret = fd;
goto out_free_linereq;
}
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);
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;
}
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;
}
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);
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;
}
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,