gpiolib-cdev.c (8db90aa36063f471bea1e65e23185913043852dc) gpiolib-cdev.c (2e202ad873365513c6ad72e29a531071dffa498a)
1// SPDX-License-Identifier: GPL-2.0
2
3#include <linux/anon_inodes.h>
4#include <linux/atomic.h>
5#include <linux/bitmap.h>
6#include <linux/build_bug.h>
7#include <linux/cdev.h>
8#include <linux/compat.h>

--- 1965 unchanged lines hidden (view full) ---

1974 DECLARE_KFIFO(events, struct gpio_v2_line_info_changed, 32);
1975 struct notifier_block lineinfo_changed_nb;
1976 unsigned long *watched_lines;
1977#ifdef CONFIG_GPIO_CDEV_V1
1978 atomic_t watch_abi_version;
1979#endif
1980};
1981
1// SPDX-License-Identifier: GPL-2.0
2
3#include <linux/anon_inodes.h>
4#include <linux/atomic.h>
5#include <linux/bitmap.h>
6#include <linux/build_bug.h>
7#include <linux/cdev.h>
8#include <linux/compat.h>

--- 1965 unchanged lines hidden (view full) ---

1974 DECLARE_KFIFO(events, struct gpio_v2_line_info_changed, 32);
1975 struct notifier_block lineinfo_changed_nb;
1976 unsigned long *watched_lines;
1977#ifdef CONFIG_GPIO_CDEV_V1
1978 atomic_t watch_abi_version;
1979#endif
1980};
1981
1982static int chipinfo_get(struct gpio_chardev_data *cdev, void __user *ip)
1983{
1984 struct gpio_device *gdev = cdev->gdev;
1985 struct gpiochip_info chipinfo;
1986
1987 memset(&chipinfo, 0, sizeof(chipinfo));
1988
1989 strscpy(chipinfo.name, dev_name(&gdev->dev), sizeof(chipinfo.name));
1990 strscpy(chipinfo.label, gdev->label, sizeof(chipinfo.label));
1991 chipinfo.lines = gdev->ngpio;
1992 if (copy_to_user(ip, &chipinfo, sizeof(chipinfo)))
1993 return -EFAULT;
1994 return 0;
1995}
1996
1982#ifdef CONFIG_GPIO_CDEV_V1
1983/*
1984 * returns 0 if the versions match, else the previously selected ABI version
1985 */
1986static int lineinfo_ensure_abi_version(struct gpio_chardev_data *cdata,
1987 unsigned int version)
1988{
1989 int abiv = atomic_cmpxchg(&cdata->watch_abi_version, 0, version);
1990
1991 if (abiv == version)
1992 return 0;
1993
1994 return abiv;
1995}
1997#ifdef CONFIG_GPIO_CDEV_V1
1998/*
1999 * returns 0 if the versions match, else the previously selected ABI version
2000 */
2001static int lineinfo_ensure_abi_version(struct gpio_chardev_data *cdata,
2002 unsigned int version)
2003{
2004 int abiv = atomic_cmpxchg(&cdata->watch_abi_version, 0, version);
2005
2006 if (abiv == version)
2007 return 0;
2008
2009 return abiv;
2010}
2011
2012static int lineinfo_get_v1(struct gpio_chardev_data *cdev, void __user *ip,
2013 bool watch)
2014{
2015 struct gpio_desc *desc;
2016 struct gpioline_info lineinfo;
2017 struct gpio_v2_line_info lineinfo_v2;
2018
2019 if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
2020 return -EFAULT;
2021
2022 /* this doubles as a range check on line_offset */
2023 desc = gpiochip_get_desc(cdev->gdev->chip, lineinfo.line_offset);
2024 if (IS_ERR(desc))
2025 return PTR_ERR(desc);
2026
2027 if (watch) {
2028 if (lineinfo_ensure_abi_version(cdev, 1))
2029 return -EPERM;
2030
2031 if (test_and_set_bit(lineinfo.line_offset, cdev->watched_lines))
2032 return -EBUSY;
2033 }
2034
2035 gpio_desc_to_lineinfo(desc, &lineinfo_v2);
2036 gpio_v2_line_info_to_v1(&lineinfo_v2, &lineinfo);
2037
2038 if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) {
2039 if (watch)
2040 clear_bit(lineinfo.line_offset, cdev->watched_lines);
2041 return -EFAULT;
2042 }
2043
2044 return 0;
2045}
1996#endif
1997
1998static int lineinfo_get(struct gpio_chardev_data *cdev, void __user *ip,
1999 bool watch)
2000{
2001 struct gpio_desc *desc;
2002 struct gpio_v2_line_info lineinfo;
2003

--- 21 unchanged lines hidden (view full) ---

2025 if (watch)
2026 clear_bit(lineinfo.offset, cdev->watched_lines);
2027 return -EFAULT;
2028 }
2029
2030 return 0;
2031}
2032
2046#endif
2047
2048static int lineinfo_get(struct gpio_chardev_data *cdev, void __user *ip,
2049 bool watch)
2050{
2051 struct gpio_desc *desc;
2052 struct gpio_v2_line_info lineinfo;
2053

--- 21 unchanged lines hidden (view full) ---

2075 if (watch)
2076 clear_bit(lineinfo.offset, cdev->watched_lines);
2077 return -EFAULT;
2078 }
2079
2080 return 0;
2081}
2082
2083static int lineinfo_unwatch(struct gpio_chardev_data *cdev, void __user *ip)
2084{
2085 __u32 offset;
2086
2087 if (copy_from_user(&offset, ip, sizeof(offset)))
2088 return -EFAULT;
2089
2090 if (offset >= cdev->gdev->ngpio)
2091 return -EINVAL;
2092
2093 if (!test_and_clear_bit(offset, cdev->watched_lines))
2094 return -EBUSY;
2095
2096 return 0;
2097}
2098
2033/*
2034 * gpio_ioctl() - ioctl handler for the GPIO chardev
2035 */
2036static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2037{
2038 struct gpio_chardev_data *cdev = file->private_data;
2039 struct gpio_device *gdev = cdev->gdev;
2099/*
2100 * gpio_ioctl() - ioctl handler for the GPIO chardev
2101 */
2102static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2103{
2104 struct gpio_chardev_data *cdev = file->private_data;
2105 struct gpio_device *gdev = cdev->gdev;
2040 struct gpio_chip *gc = gdev->chip;
2041 void __user *ip = (void __user *)arg;
2106 void __user *ip = (void __user *)arg;
2042 __u32 offset;
2043
2044 /* We fail any subsequent ioctl():s when the chip is gone */
2107
2108 /* We fail any subsequent ioctl():s when the chip is gone */
2045 if (!gc)
2109 if (!gdev->chip)
2046 return -ENODEV;
2047
2048 /* Fill in the struct and pass to userspace */
2049 if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
2110 return -ENODEV;
2111
2112 /* Fill in the struct and pass to userspace */
2113 if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
2050 struct gpiochip_info chipinfo;
2051
2052 memset(&chipinfo, 0, sizeof(chipinfo));
2053
2054 strscpy(chipinfo.name, dev_name(&gdev->dev),
2055 sizeof(chipinfo.name));
2056 strscpy(chipinfo.label, gdev->label,
2057 sizeof(chipinfo.label));
2058 chipinfo.lines = gdev->ngpio;
2059 if (copy_to_user(ip, &chipinfo, sizeof(chipinfo)))
2060 return -EFAULT;
2061 return 0;
2114 return chipinfo_get(cdev, ip);
2062#ifdef CONFIG_GPIO_CDEV_V1
2115#ifdef CONFIG_GPIO_CDEV_V1
2063 } else if (cmd == GPIO_GET_LINEINFO_IOCTL) {
2064 struct gpio_desc *desc;
2065 struct gpioline_info lineinfo;
2066 struct gpio_v2_line_info lineinfo_v2;
2067
2068 if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
2069 return -EFAULT;
2070
2071 /* this doubles as a range check on line_offset */
2072 desc = gpiochip_get_desc(gc, lineinfo.line_offset);
2073 if (IS_ERR(desc))
2074 return PTR_ERR(desc);
2075
2076 gpio_desc_to_lineinfo(desc, &lineinfo_v2);
2077 gpio_v2_line_info_to_v1(&lineinfo_v2, &lineinfo);
2078
2079 if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
2080 return -EFAULT;
2081 return 0;
2082 } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
2083 return linehandle_create(gdev, ip);
2084 } else if (cmd == GPIO_GET_LINEEVENT_IOCTL) {
2085 return lineevent_create(gdev, ip);
2116 } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
2117 return linehandle_create(gdev, ip);
2118 } else if (cmd == GPIO_GET_LINEEVENT_IOCTL) {
2119 return lineevent_create(gdev, ip);
2086 } else if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) {
2087 struct gpio_desc *desc;
2088 struct gpioline_info lineinfo;
2089 struct gpio_v2_line_info lineinfo_v2;
2090
2091 if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
2092 return -EFAULT;
2093
2094 /* this doubles as a range check on line_offset */
2095 desc = gpiochip_get_desc(gc, lineinfo.line_offset);
2096 if (IS_ERR(desc))
2097 return PTR_ERR(desc);
2098
2099 if (lineinfo_ensure_abi_version(cdev, 1))
2100 return -EPERM;
2101
2102 if (test_and_set_bit(lineinfo.line_offset, cdev->watched_lines))
2103 return -EBUSY;
2104
2105 gpio_desc_to_lineinfo(desc, &lineinfo_v2);
2106 gpio_v2_line_info_to_v1(&lineinfo_v2, &lineinfo);
2107
2108 if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) {
2109 clear_bit(lineinfo.line_offset, cdev->watched_lines);
2110 return -EFAULT;
2111 }
2112
2113 return 0;
2120 } else if (cmd == GPIO_GET_LINEINFO_IOCTL ||
2121 cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) {
2122 return lineinfo_get_v1(cdev, ip,
2123 cmd == GPIO_GET_LINEINFO_WATCH_IOCTL);
2114#endif /* CONFIG_GPIO_CDEV_V1 */
2115 } else if (cmd == GPIO_V2_GET_LINEINFO_IOCTL ||
2116 cmd == GPIO_V2_GET_LINEINFO_WATCH_IOCTL) {
2117 return lineinfo_get(cdev, ip,
2118 cmd == GPIO_V2_GET_LINEINFO_WATCH_IOCTL);
2119 } else if (cmd == GPIO_V2_GET_LINE_IOCTL) {
2120 return linereq_create(gdev, ip);
2121 } else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) {
2124#endif /* CONFIG_GPIO_CDEV_V1 */
2125 } else if (cmd == GPIO_V2_GET_LINEINFO_IOCTL ||
2126 cmd == GPIO_V2_GET_LINEINFO_WATCH_IOCTL) {
2127 return lineinfo_get(cdev, ip,
2128 cmd == GPIO_V2_GET_LINEINFO_WATCH_IOCTL);
2129 } else if (cmd == GPIO_V2_GET_LINE_IOCTL) {
2130 return linereq_create(gdev, ip);
2131 } else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) {
2122 if (copy_from_user(&offset, ip, sizeof(offset)))
2123 return -EFAULT;
2124
2125 if (offset >= cdev->gdev->ngpio)
2126 return -EINVAL;
2127
2128 if (!test_and_clear_bit(offset, cdev->watched_lines))
2129 return -EBUSY;
2130
2131 return 0;
2132 return lineinfo_unwatch(cdev, ip);
2132 }
2133 return -EINVAL;
2134}
2135
2136#ifdef CONFIG_COMPAT
2137static long gpio_ioctl_compat(struct file *file, unsigned int cmd,
2138 unsigned long arg)
2139{

--- 235 unchanged lines hidden ---
2133 }
2134 return -EINVAL;
2135}
2136
2137#ifdef CONFIG_COMPAT
2138static long gpio_ioctl_compat(struct file *file, unsigned int cmd,
2139 unsigned long arg)
2140{

--- 235 unchanged lines hidden ---