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 --- |