mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-17 00:12:55 -04:00
gpio: convert linehandle_create() to FD_PREPARE()
Link: https://patch.msgid.link/20251123-work-fd-prepare-v4-38-b6efa1706cfd@kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
@@ -298,12 +298,13 @@ static const struct file_operations linehandle_fileops = {
|
||||
#endif
|
||||
};
|
||||
|
||||
DEFINE_FREE(linehandle_free, struct linehandle_state *, if (!IS_ERR_OR_NULL(_T)) linehandle_free(_T))
|
||||
|
||||
static int linehandle_create(struct gpio_device *gdev, void __user *ip)
|
||||
{
|
||||
struct gpiohandle_request handlereq;
|
||||
struct linehandle_state *lh;
|
||||
struct file *file;
|
||||
int fd, i, ret;
|
||||
struct linehandle_state *lh __free(linehandle_free) = NULL;
|
||||
int i, ret;
|
||||
u32 lflags;
|
||||
|
||||
if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
|
||||
@@ -327,10 +328,8 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
|
||||
lh->label = kstrndup(handlereq.consumer_label,
|
||||
sizeof(handlereq.consumer_label) - 1,
|
||||
GFP_KERNEL);
|
||||
if (!lh->label) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free_lh;
|
||||
}
|
||||
if (!lh->label)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
lh->num_descs = handlereq.lines;
|
||||
@@ -340,20 +339,18 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
|
||||
u32 offset = handlereq.lineoffsets[i];
|
||||
struct gpio_desc *desc = gpio_device_get_desc(gdev, offset);
|
||||
|
||||
if (IS_ERR(desc)) {
|
||||
ret = PTR_ERR(desc);
|
||||
goto out_free_lh;
|
||||
}
|
||||
if (IS_ERR(desc))
|
||||
return PTR_ERR(desc);
|
||||
|
||||
ret = gpiod_request_user(desc, lh->label);
|
||||
if (ret)
|
||||
goto out_free_lh;
|
||||
return ret;
|
||||
lh->descs[i] = desc;
|
||||
linehandle_flags_to_desc_flags(handlereq.flags, &desc->flags);
|
||||
|
||||
ret = gpiod_set_transitory(desc, false);
|
||||
if (ret < 0)
|
||||
goto out_free_lh;
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Lines have to be requested explicitly for input
|
||||
@@ -364,11 +361,11 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
|
||||
|
||||
ret = gpiod_direction_output_nonotify(desc, val);
|
||||
if (ret)
|
||||
goto out_free_lh;
|
||||
return ret;
|
||||
} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
|
||||
ret = gpiod_direction_input_nonotify(desc);
|
||||
if (ret)
|
||||
goto out_free_lh;
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED);
|
||||
@@ -377,44 +374,23 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
|
||||
offset);
|
||||
}
|
||||
|
||||
fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
ret = fd;
|
||||
goto out_free_lh;
|
||||
}
|
||||
FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC,
|
||||
anon_inode_getfile("gpio-linehandle", &linehandle_fileops,
|
||||
lh, O_RDONLY | O_CLOEXEC));
|
||||
if (fdf.err)
|
||||
return fdf.err;
|
||||
retain_and_null_ptr(lh);
|
||||
|
||||
file = anon_inode_getfile("gpio-linehandle",
|
||||
&linehandle_fileops,
|
||||
lh,
|
||||
O_RDONLY | O_CLOEXEC);
|
||||
if (IS_ERR(file)) {
|
||||
ret = PTR_ERR(file);
|
||||
goto out_put_unused_fd;
|
||||
}
|
||||
|
||||
handlereq.fd = fd;
|
||||
if (copy_to_user(ip, &handlereq, sizeof(handlereq))) {
|
||||
/*
|
||||
* fput() will trigger the release() callback, so do not go onto
|
||||
* the regular error cleanup path here.
|
||||
*/
|
||||
fput(file);
|
||||
put_unused_fd(fd);
|
||||
handlereq.fd = fd_prepare_fd(fdf);
|
||||
if (copy_to_user(ip, &handlereq, sizeof(handlereq)))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
fd_install(fd, file);
|
||||
fd_publish(fdf);
|
||||
|
||||
dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
|
||||
lh->num_descs);
|
||||
|
||||
return 0;
|
||||
|
||||
out_put_unused_fd:
|
||||
put_unused_fd(fd);
|
||||
out_free_lh:
|
||||
linehandle_free(lh);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_GPIO_CDEV_V1 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user