mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 10:33:41 +02:00
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:
parent
2c46f19c9a
commit
96c02c906a
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user