mirror of
https://github.com/torvalds/linux.git
synced 2026-05-23 22:52:19 +02: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:
parent
6ae8da4846
commit
da7e394bf5
|
|
@ -298,12 +298,13 @@ static const struct file_operations linehandle_fileops = {
|
||||||
#endif
|
#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)
|
static int linehandle_create(struct gpio_device *gdev, void __user *ip)
|
||||||
{
|
{
|
||||||
struct gpiohandle_request handlereq;
|
struct gpiohandle_request handlereq;
|
||||||
struct linehandle_state *lh;
|
struct linehandle_state *lh __free(linehandle_free) = NULL;
|
||||||
struct file *file;
|
int i, ret;
|
||||||
int fd, i, ret;
|
|
||||||
u32 lflags;
|
u32 lflags;
|
||||||
|
|
||||||
if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
|
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,
|
lh->label = kstrndup(handlereq.consumer_label,
|
||||||
sizeof(handlereq.consumer_label) - 1,
|
sizeof(handlereq.consumer_label) - 1,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!lh->label) {
|
if (!lh->label)
|
||||||
ret = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto out_free_lh;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lh->num_descs = handlereq.lines;
|
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];
|
u32 offset = handlereq.lineoffsets[i];
|
||||||
struct gpio_desc *desc = gpio_device_get_desc(gdev, offset);
|
struct gpio_desc *desc = gpio_device_get_desc(gdev, offset);
|
||||||
|
|
||||||
if (IS_ERR(desc)) {
|
if (IS_ERR(desc))
|
||||||
ret = PTR_ERR(desc);
|
return PTR_ERR(desc);
|
||||||
goto out_free_lh;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = gpiod_request_user(desc, lh->label);
|
ret = gpiod_request_user(desc, lh->label);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_free_lh;
|
return ret;
|
||||||
lh->descs[i] = desc;
|
lh->descs[i] = desc;
|
||||||
linehandle_flags_to_desc_flags(handlereq.flags, &desc->flags);
|
linehandle_flags_to_desc_flags(handlereq.flags, &desc->flags);
|
||||||
|
|
||||||
ret = gpiod_set_transitory(desc, false);
|
ret = gpiod_set_transitory(desc, false);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_free_lh;
|
return ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lines have to be requested explicitly for input
|
* 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);
|
ret = gpiod_direction_output_nonotify(desc, val);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_free_lh;
|
return ret;
|
||||||
} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
|
} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
|
||||||
ret = gpiod_direction_input_nonotify(desc);
|
ret = gpiod_direction_input_nonotify(desc);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_free_lh;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED);
|
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);
|
offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
|
FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC,
|
||||||
if (fd < 0) {
|
anon_inode_getfile("gpio-linehandle", &linehandle_fileops,
|
||||||
ret = fd;
|
lh, O_RDONLY | O_CLOEXEC));
|
||||||
goto out_free_lh;
|
if (fdf.err)
|
||||||
}
|
return fdf.err;
|
||||||
|
retain_and_null_ptr(lh);
|
||||||
|
|
||||||
file = anon_inode_getfile("gpio-linehandle",
|
handlereq.fd = fd_prepare_fd(fdf);
|
||||||
&linehandle_fileops,
|
if (copy_to_user(ip, &handlereq, sizeof(handlereq)))
|
||||||
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);
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
|
||||||
|
|
||||||
fd_install(fd, file);
|
fd_publish(fdf);
|
||||||
|
|
||||||
dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
|
dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
|
||||||
lh->num_descs);
|
lh->num_descs);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_put_unused_fd:
|
|
||||||
put_unused_fd(fd);
|
|
||||||
out_free_lh:
|
|
||||||
linehandle_free(lh);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_GPIO_CDEV_V1 */
|
#endif /* CONFIG_GPIO_CDEV_V1 */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user