xref: /openbmc/linux/drivers/gpio/gpiolib-cdev.c (revision 3c0d9c635ae2b2c6416928271a452017b60e3f98)
1925ca369SKent Gibson // SPDX-License-Identifier: GPL-2.0
2925ca369SKent Gibson 
3d189f627SKent Gibson #include <linux/anon_inodes.h>
4*3c0d9c63SKent Gibson #include <linux/atomic.h>
5925ca369SKent Gibson #include <linux/bitmap.h>
6*3c0d9c63SKent Gibson #include <linux/build_bug.h>
7d189f627SKent Gibson #include <linux/cdev.h>
8d189f627SKent Gibson #include <linux/compat.h>
9925ca369SKent Gibson #include <linux/device.h>
10925ca369SKent Gibson #include <linux/err.h>
11d189f627SKent Gibson #include <linux/file.h>
12925ca369SKent Gibson #include <linux/gpio.h>
13925ca369SKent Gibson #include <linux/gpio/driver.h>
14d189f627SKent Gibson #include <linux/interrupt.h>
15d189f627SKent Gibson #include <linux/irqreturn.h>
16d189f627SKent Gibson #include <linux/kernel.h>
17925ca369SKent Gibson #include <linux/kfifo.h>
18d189f627SKent Gibson #include <linux/module.h>
19d189f627SKent Gibson #include <linux/pinctrl/consumer.h>
20925ca369SKent Gibson #include <linux/poll.h>
21d189f627SKent Gibson #include <linux/spinlock.h>
22925ca369SKent Gibson #include <linux/timekeeping.h>
23d189f627SKent Gibson #include <linux/uaccess.h>
24925ca369SKent Gibson #include <uapi/linux/gpio.h>
25925ca369SKent Gibson 
26925ca369SKent Gibson #include "gpiolib.h"
27925ca369SKent Gibson #include "gpiolib-cdev.h"
28925ca369SKent Gibson 
29*3c0d9c63SKent Gibson /*
30*3c0d9c63SKent Gibson  * Array sizes must ensure 64-bit alignment and not create holes in the
31*3c0d9c63SKent Gibson  * struct packing.
32*3c0d9c63SKent Gibson  */
33*3c0d9c63SKent Gibson static_assert(IS_ALIGNED(GPIO_V2_LINES_MAX, 2));
34*3c0d9c63SKent Gibson static_assert(IS_ALIGNED(GPIO_MAX_NAME_SIZE, 8));
35*3c0d9c63SKent Gibson 
36*3c0d9c63SKent Gibson /*
37*3c0d9c63SKent Gibson  * Check that uAPI structs are 64-bit aligned for 32/64-bit compatibility
38*3c0d9c63SKent Gibson  */
39*3c0d9c63SKent Gibson static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_attribute), 8));
40*3c0d9c63SKent Gibson static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_config_attribute), 8));
41*3c0d9c63SKent Gibson static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_config), 8));
42*3c0d9c63SKent Gibson static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_request), 8));
43*3c0d9c63SKent Gibson static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_info), 8));
44*3c0d9c63SKent Gibson static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_info_changed), 8));
45*3c0d9c63SKent Gibson static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_event), 8));
46*3c0d9c63SKent Gibson static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_values), 8));
47*3c0d9c63SKent Gibson 
48925ca369SKent Gibson /* Character device interface to GPIO.
49925ca369SKent Gibson  *
50925ca369SKent Gibson  * The GPIO character device, /dev/gpiochipN, provides userspace an
51925ca369SKent Gibson  * interface to gpiolib GPIOs via ioctl()s.
52925ca369SKent Gibson  */
53925ca369SKent Gibson 
54925ca369SKent Gibson /*
55925ca369SKent Gibson  * GPIO line handle management
56925ca369SKent Gibson  */
57925ca369SKent Gibson 
58*3c0d9c63SKent Gibson #ifdef CONFIG_GPIO_CDEV_V1
59925ca369SKent Gibson /**
60925ca369SKent Gibson  * struct linehandle_state - contains the state of a userspace handle
61925ca369SKent Gibson  * @gdev: the GPIO device the handle pertains to
62925ca369SKent Gibson  * @label: consumer label used to tag descriptors
63925ca369SKent Gibson  * @descs: the GPIO descriptors held by this handle
6452b7b596SKent Gibson  * @num_descs: the number of descriptors held in the descs array
65925ca369SKent Gibson  */
66925ca369SKent Gibson struct linehandle_state {
67925ca369SKent Gibson 	struct gpio_device *gdev;
68925ca369SKent Gibson 	const char *label;
69925ca369SKent Gibson 	struct gpio_desc *descs[GPIOHANDLES_MAX];
7052b7b596SKent Gibson 	u32 num_descs;
71925ca369SKent Gibson };
72925ca369SKent Gibson 
73925ca369SKent Gibson #define GPIOHANDLE_REQUEST_VALID_FLAGS \
74925ca369SKent Gibson 	(GPIOHANDLE_REQUEST_INPUT | \
75925ca369SKent Gibson 	GPIOHANDLE_REQUEST_OUTPUT | \
76925ca369SKent Gibson 	GPIOHANDLE_REQUEST_ACTIVE_LOW | \
77925ca369SKent Gibson 	GPIOHANDLE_REQUEST_BIAS_PULL_UP | \
78925ca369SKent Gibson 	GPIOHANDLE_REQUEST_BIAS_PULL_DOWN | \
79925ca369SKent Gibson 	GPIOHANDLE_REQUEST_BIAS_DISABLE | \
80925ca369SKent Gibson 	GPIOHANDLE_REQUEST_OPEN_DRAIN | \
81925ca369SKent Gibson 	GPIOHANDLE_REQUEST_OPEN_SOURCE)
82925ca369SKent Gibson 
83925ca369SKent Gibson static int linehandle_validate_flags(u32 flags)
84925ca369SKent Gibson {
85925ca369SKent Gibson 	/* Return an error if an unknown flag is set */
86925ca369SKent Gibson 	if (flags & ~GPIOHANDLE_REQUEST_VALID_FLAGS)
87925ca369SKent Gibson 		return -EINVAL;
88925ca369SKent Gibson 
89925ca369SKent Gibson 	/*
90925ca369SKent Gibson 	 * Do not allow both INPUT & OUTPUT flags to be set as they are
91925ca369SKent Gibson 	 * contradictory.
92925ca369SKent Gibson 	 */
93925ca369SKent Gibson 	if ((flags & GPIOHANDLE_REQUEST_INPUT) &&
94925ca369SKent Gibson 	    (flags & GPIOHANDLE_REQUEST_OUTPUT))
95925ca369SKent Gibson 		return -EINVAL;
96925ca369SKent Gibson 
97925ca369SKent Gibson 	/*
98925ca369SKent Gibson 	 * Do not allow OPEN_SOURCE & OPEN_DRAIN flags in a single request. If
99925ca369SKent Gibson 	 * the hardware actually supports enabling both at the same time the
100925ca369SKent Gibson 	 * electrical result would be disastrous.
101925ca369SKent Gibson 	 */
102925ca369SKent Gibson 	if ((flags & GPIOHANDLE_REQUEST_OPEN_DRAIN) &&
103925ca369SKent Gibson 	    (flags & GPIOHANDLE_REQUEST_OPEN_SOURCE))
104925ca369SKent Gibson 		return -EINVAL;
105925ca369SKent Gibson 
106925ca369SKent Gibson 	/* OPEN_DRAIN and OPEN_SOURCE flags only make sense for output mode. */
107925ca369SKent Gibson 	if (!(flags & GPIOHANDLE_REQUEST_OUTPUT) &&
108925ca369SKent Gibson 	    ((flags & GPIOHANDLE_REQUEST_OPEN_DRAIN) ||
109925ca369SKent Gibson 	     (flags & GPIOHANDLE_REQUEST_OPEN_SOURCE)))
110925ca369SKent Gibson 		return -EINVAL;
111925ca369SKent Gibson 
112925ca369SKent Gibson 	/* Bias flags only allowed for input or output mode. */
113925ca369SKent Gibson 	if (!((flags & GPIOHANDLE_REQUEST_INPUT) ||
114925ca369SKent Gibson 	      (flags & GPIOHANDLE_REQUEST_OUTPUT)) &&
115925ca369SKent Gibson 	    ((flags & GPIOHANDLE_REQUEST_BIAS_DISABLE) ||
116925ca369SKent Gibson 	     (flags & GPIOHANDLE_REQUEST_BIAS_PULL_UP) ||
117925ca369SKent Gibson 	     (flags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN)))
118925ca369SKent Gibson 		return -EINVAL;
119925ca369SKent Gibson 
120925ca369SKent Gibson 	/* Only one bias flag can be set. */
121925ca369SKent Gibson 	if (((flags & GPIOHANDLE_REQUEST_BIAS_DISABLE) &&
122925ca369SKent Gibson 	     (flags & (GPIOHANDLE_REQUEST_BIAS_PULL_DOWN |
123925ca369SKent Gibson 		       GPIOHANDLE_REQUEST_BIAS_PULL_UP))) ||
124925ca369SKent Gibson 	    ((flags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) &&
125925ca369SKent Gibson 	     (flags & GPIOHANDLE_REQUEST_BIAS_PULL_UP)))
126925ca369SKent Gibson 		return -EINVAL;
127925ca369SKent Gibson 
128925ca369SKent Gibson 	return 0;
129925ca369SKent Gibson }
130925ca369SKent Gibson 
131c274b58aSKent Gibson static void linehandle_flags_to_desc_flags(u32 lflags, unsigned long *flagsp)
132c274b58aSKent Gibson {
133c274b58aSKent Gibson 	assign_bit(FLAG_ACTIVE_LOW, flagsp,
134c274b58aSKent Gibson 		   lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW);
135c274b58aSKent Gibson 	assign_bit(FLAG_OPEN_DRAIN, flagsp,
136c274b58aSKent Gibson 		   lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN);
137c274b58aSKent Gibson 	assign_bit(FLAG_OPEN_SOURCE, flagsp,
138c274b58aSKent Gibson 		   lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE);
139c274b58aSKent Gibson 	assign_bit(FLAG_PULL_UP, flagsp,
140c274b58aSKent Gibson 		   lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP);
141c274b58aSKent Gibson 	assign_bit(FLAG_PULL_DOWN, flagsp,
142c274b58aSKent Gibson 		   lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN);
143c274b58aSKent Gibson 	assign_bit(FLAG_BIAS_DISABLE, flagsp,
144c274b58aSKent Gibson 		   lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE);
145c274b58aSKent Gibson }
146c274b58aSKent Gibson 
147925ca369SKent Gibson static long linehandle_set_config(struct linehandle_state *lh,
148925ca369SKent Gibson 				  void __user *ip)
149925ca369SKent Gibson {
150925ca369SKent Gibson 	struct gpiohandle_config gcnf;
151925ca369SKent Gibson 	struct gpio_desc *desc;
152925ca369SKent Gibson 	int i, ret;
153925ca369SKent Gibson 	u32 lflags;
154925ca369SKent Gibson 
155925ca369SKent Gibson 	if (copy_from_user(&gcnf, ip, sizeof(gcnf)))
156925ca369SKent Gibson 		return -EFAULT;
157925ca369SKent Gibson 
158925ca369SKent Gibson 	lflags = gcnf.flags;
159925ca369SKent Gibson 	ret = linehandle_validate_flags(lflags);
160925ca369SKent Gibson 	if (ret)
161925ca369SKent Gibson 		return ret;
162925ca369SKent Gibson 
16352b7b596SKent Gibson 	for (i = 0; i < lh->num_descs; i++) {
164925ca369SKent Gibson 		desc = lh->descs[i];
165c274b58aSKent Gibson 		linehandle_flags_to_desc_flags(gcnf.flags, &desc->flags);
166925ca369SKent Gibson 
167925ca369SKent Gibson 		/*
168925ca369SKent Gibson 		 * Lines have to be requested explicitly for input
169925ca369SKent Gibson 		 * or output, else the line will be treated "as is".
170925ca369SKent Gibson 		 */
171925ca369SKent Gibson 		if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
172925ca369SKent Gibson 			int val = !!gcnf.default_values[i];
173925ca369SKent Gibson 
174925ca369SKent Gibson 			ret = gpiod_direction_output(desc, val);
175925ca369SKent Gibson 			if (ret)
176925ca369SKent Gibson 				return ret;
177925ca369SKent Gibson 		} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
178925ca369SKent Gibson 			ret = gpiod_direction_input(desc);
179925ca369SKent Gibson 			if (ret)
180925ca369SKent Gibson 				return ret;
181925ca369SKent Gibson 		}
182925ca369SKent Gibson 
1836accc376SKent Gibson 		blocking_notifier_call_chain(&desc->gdev->notifier,
184925ca369SKent Gibson 					     GPIOLINE_CHANGED_CONFIG, desc);
185925ca369SKent Gibson 	}
186925ca369SKent Gibson 	return 0;
187925ca369SKent Gibson }
188925ca369SKent Gibson 
18949bc5279SKent Gibson static long linehandle_ioctl(struct file *file, unsigned int cmd,
190925ca369SKent Gibson 			     unsigned long arg)
191925ca369SKent Gibson {
19249bc5279SKent Gibson 	struct linehandle_state *lh = file->private_data;
193925ca369SKent Gibson 	void __user *ip = (void __user *)arg;
194925ca369SKent Gibson 	struct gpiohandle_data ghd;
195925ca369SKent Gibson 	DECLARE_BITMAP(vals, GPIOHANDLES_MAX);
196925ca369SKent Gibson 	int i;
197925ca369SKent Gibson 
198925ca369SKent Gibson 	if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
199925ca369SKent Gibson 		/* NOTE: It's ok to read values of output lines. */
200925ca369SKent Gibson 		int ret = gpiod_get_array_value_complex(false,
201925ca369SKent Gibson 							true,
20252b7b596SKent Gibson 							lh->num_descs,
203925ca369SKent Gibson 							lh->descs,
204925ca369SKent Gibson 							NULL,
205925ca369SKent Gibson 							vals);
206925ca369SKent Gibson 		if (ret)
207925ca369SKent Gibson 			return ret;
208925ca369SKent Gibson 
209925ca369SKent Gibson 		memset(&ghd, 0, sizeof(ghd));
21052b7b596SKent Gibson 		for (i = 0; i < lh->num_descs; i++)
211925ca369SKent Gibson 			ghd.values[i] = test_bit(i, vals);
212925ca369SKent Gibson 
213925ca369SKent Gibson 		if (copy_to_user(ip, &ghd, sizeof(ghd)))
214925ca369SKent Gibson 			return -EFAULT;
215925ca369SKent Gibson 
216925ca369SKent Gibson 		return 0;
217925ca369SKent Gibson 	} else if (cmd == GPIOHANDLE_SET_LINE_VALUES_IOCTL) {
218925ca369SKent Gibson 		/*
219925ca369SKent Gibson 		 * All line descriptors were created at once with the same
220925ca369SKent Gibson 		 * flags so just check if the first one is really output.
221925ca369SKent Gibson 		 */
222925ca369SKent Gibson 		if (!test_bit(FLAG_IS_OUT, &lh->descs[0]->flags))
223925ca369SKent Gibson 			return -EPERM;
224925ca369SKent Gibson 
225925ca369SKent Gibson 		if (copy_from_user(&ghd, ip, sizeof(ghd)))
226925ca369SKent Gibson 			return -EFAULT;
227925ca369SKent Gibson 
228925ca369SKent Gibson 		/* Clamp all values to [0,1] */
22952b7b596SKent Gibson 		for (i = 0; i < lh->num_descs; i++)
230925ca369SKent Gibson 			__assign_bit(i, vals, ghd.values[i]);
231925ca369SKent Gibson 
232925ca369SKent Gibson 		/* Reuse the array setting function */
233925ca369SKent Gibson 		return gpiod_set_array_value_complex(false,
234925ca369SKent Gibson 						     true,
23552b7b596SKent Gibson 						     lh->num_descs,
236925ca369SKent Gibson 						     lh->descs,
237925ca369SKent Gibson 						     NULL,
238925ca369SKent Gibson 						     vals);
239925ca369SKent Gibson 	} else if (cmd == GPIOHANDLE_SET_CONFIG_IOCTL) {
240925ca369SKent Gibson 		return linehandle_set_config(lh, ip);
241925ca369SKent Gibson 	}
242925ca369SKent Gibson 	return -EINVAL;
243925ca369SKent Gibson }
244925ca369SKent Gibson 
245925ca369SKent Gibson #ifdef CONFIG_COMPAT
24649bc5279SKent Gibson static long linehandle_ioctl_compat(struct file *file, unsigned int cmd,
247925ca369SKent Gibson 				    unsigned long arg)
248925ca369SKent Gibson {
24949bc5279SKent Gibson 	return linehandle_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
250925ca369SKent Gibson }
251925ca369SKent Gibson #endif
252925ca369SKent Gibson 
253883f9198SKent Gibson static void linehandle_free(struct linehandle_state *lh)
254925ca369SKent Gibson {
255925ca369SKent Gibson 	int i;
256925ca369SKent Gibson 
25752b7b596SKent Gibson 	for (i = 0; i < lh->num_descs; i++)
258883f9198SKent Gibson 		if (lh->descs[i])
259925ca369SKent Gibson 			gpiod_free(lh->descs[i]);
260925ca369SKent Gibson 	kfree(lh->label);
261883f9198SKent Gibson 	put_device(&lh->gdev->dev);
262925ca369SKent Gibson 	kfree(lh);
263883f9198SKent Gibson }
264883f9198SKent Gibson 
265883f9198SKent Gibson static int linehandle_release(struct inode *inode, struct file *file)
266883f9198SKent Gibson {
267883f9198SKent Gibson 	linehandle_free(file->private_data);
268925ca369SKent Gibson 	return 0;
269925ca369SKent Gibson }
270925ca369SKent Gibson 
271925ca369SKent Gibson static const struct file_operations linehandle_fileops = {
272925ca369SKent Gibson 	.release = linehandle_release,
273925ca369SKent Gibson 	.owner = THIS_MODULE,
274925ca369SKent Gibson 	.llseek = noop_llseek,
275925ca369SKent Gibson 	.unlocked_ioctl = linehandle_ioctl,
276925ca369SKent Gibson #ifdef CONFIG_COMPAT
277925ca369SKent Gibson 	.compat_ioctl = linehandle_ioctl_compat,
278925ca369SKent Gibson #endif
279925ca369SKent Gibson };
280925ca369SKent Gibson 
281925ca369SKent Gibson static int linehandle_create(struct gpio_device *gdev, void __user *ip)
282925ca369SKent Gibson {
283925ca369SKent Gibson 	struct gpiohandle_request handlereq;
284925ca369SKent Gibson 	struct linehandle_state *lh;
285925ca369SKent Gibson 	struct file *file;
286883f9198SKent Gibson 	int fd, i, ret;
287925ca369SKent Gibson 	u32 lflags;
288925ca369SKent Gibson 
289925ca369SKent Gibson 	if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
290925ca369SKent Gibson 		return -EFAULT;
291925ca369SKent Gibson 	if ((handlereq.lines == 0) || (handlereq.lines > GPIOHANDLES_MAX))
292925ca369SKent Gibson 		return -EINVAL;
293925ca369SKent Gibson 
294925ca369SKent Gibson 	lflags = handlereq.flags;
295925ca369SKent Gibson 
296925ca369SKent Gibson 	ret = linehandle_validate_flags(lflags);
297925ca369SKent Gibson 	if (ret)
298925ca369SKent Gibson 		return ret;
299925ca369SKent Gibson 
300925ca369SKent Gibson 	lh = kzalloc(sizeof(*lh), GFP_KERNEL);
301925ca369SKent Gibson 	if (!lh)
302925ca369SKent Gibson 		return -ENOMEM;
303925ca369SKent Gibson 	lh->gdev = gdev;
304925ca369SKent Gibson 	get_device(&gdev->dev);
305925ca369SKent Gibson 
306925ca369SKent Gibson 	/* Make sure this is terminated */
307925ca369SKent Gibson 	handlereq.consumer_label[sizeof(handlereq.consumer_label)-1] = '\0';
308925ca369SKent Gibson 	if (strlen(handlereq.consumer_label)) {
309925ca369SKent Gibson 		lh->label = kstrdup(handlereq.consumer_label,
310925ca369SKent Gibson 				    GFP_KERNEL);
311925ca369SKent Gibson 		if (!lh->label) {
312925ca369SKent Gibson 			ret = -ENOMEM;
313925ca369SKent Gibson 			goto out_free_lh;
314925ca369SKent Gibson 		}
315925ca369SKent Gibson 	}
316925ca369SKent Gibson 
317883f9198SKent Gibson 	lh->num_descs = handlereq.lines;
318883f9198SKent Gibson 
319925ca369SKent Gibson 	/* Request each GPIO */
320925ca369SKent Gibson 	for (i = 0; i < handlereq.lines; i++) {
321925ca369SKent Gibson 		u32 offset = handlereq.lineoffsets[i];
322925ca369SKent Gibson 		struct gpio_desc *desc = gpiochip_get_desc(gdev->chip, offset);
323925ca369SKent Gibson 
324925ca369SKent Gibson 		if (IS_ERR(desc)) {
325925ca369SKent Gibson 			ret = PTR_ERR(desc);
326883f9198SKent Gibson 			goto out_free_lh;
327925ca369SKent Gibson 		}
328925ca369SKent Gibson 
329925ca369SKent Gibson 		ret = gpiod_request(desc, lh->label);
330925ca369SKent Gibson 		if (ret)
331883f9198SKent Gibson 			goto out_free_lh;
332925ca369SKent Gibson 		lh->descs[i] = desc;
333c274b58aSKent Gibson 		linehandle_flags_to_desc_flags(handlereq.flags, &desc->flags);
334925ca369SKent Gibson 
335925ca369SKent Gibson 		ret = gpiod_set_transitory(desc, false);
336925ca369SKent Gibson 		if (ret < 0)
337883f9198SKent Gibson 			goto out_free_lh;
338925ca369SKent Gibson 
339925ca369SKent Gibson 		/*
340925ca369SKent Gibson 		 * Lines have to be requested explicitly for input
341925ca369SKent Gibson 		 * or output, else the line will be treated "as is".
342925ca369SKent Gibson 		 */
343925ca369SKent Gibson 		if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
344925ca369SKent Gibson 			int val = !!handlereq.default_values[i];
345925ca369SKent Gibson 
346925ca369SKent Gibson 			ret = gpiod_direction_output(desc, val);
347925ca369SKent Gibson 			if (ret)
348883f9198SKent Gibson 				goto out_free_lh;
349925ca369SKent Gibson 		} else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
350925ca369SKent Gibson 			ret = gpiod_direction_input(desc);
351925ca369SKent Gibson 			if (ret)
352883f9198SKent Gibson 				goto out_free_lh;
353925ca369SKent Gibson 		}
354925ca369SKent Gibson 
3556accc376SKent Gibson 		blocking_notifier_call_chain(&desc->gdev->notifier,
356925ca369SKent Gibson 					     GPIOLINE_CHANGED_REQUESTED, desc);
357925ca369SKent Gibson 
358925ca369SKent Gibson 		dev_dbg(&gdev->dev, "registered chardev handle for line %d\n",
359925ca369SKent Gibson 			offset);
360925ca369SKent Gibson 	}
361925ca369SKent Gibson 
362925ca369SKent Gibson 	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
363925ca369SKent Gibson 	if (fd < 0) {
364925ca369SKent Gibson 		ret = fd;
365883f9198SKent Gibson 		goto out_free_lh;
366925ca369SKent Gibson 	}
367925ca369SKent Gibson 
368925ca369SKent Gibson 	file = anon_inode_getfile("gpio-linehandle",
369925ca369SKent Gibson 				  &linehandle_fileops,
370925ca369SKent Gibson 				  lh,
371925ca369SKent Gibson 				  O_RDONLY | O_CLOEXEC);
372925ca369SKent Gibson 	if (IS_ERR(file)) {
373925ca369SKent Gibson 		ret = PTR_ERR(file);
374925ca369SKent Gibson 		goto out_put_unused_fd;
375925ca369SKent Gibson 	}
376925ca369SKent Gibson 
377925ca369SKent Gibson 	handlereq.fd = fd;
378925ca369SKent Gibson 	if (copy_to_user(ip, &handlereq, sizeof(handlereq))) {
379925ca369SKent Gibson 		/*
380925ca369SKent Gibson 		 * fput() will trigger the release() callback, so do not go onto
381925ca369SKent Gibson 		 * the regular error cleanup path here.
382925ca369SKent Gibson 		 */
383925ca369SKent Gibson 		fput(file);
384925ca369SKent Gibson 		put_unused_fd(fd);
385925ca369SKent Gibson 		return -EFAULT;
386925ca369SKent Gibson 	}
387925ca369SKent Gibson 
388925ca369SKent Gibson 	fd_install(fd, file);
389925ca369SKent Gibson 
390925ca369SKent Gibson 	dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
39152b7b596SKent Gibson 		lh->num_descs);
392925ca369SKent Gibson 
393925ca369SKent Gibson 	return 0;
394925ca369SKent Gibson 
395925ca369SKent Gibson out_put_unused_fd:
396925ca369SKent Gibson 	put_unused_fd(fd);
397925ca369SKent Gibson out_free_lh:
398883f9198SKent Gibson 	linehandle_free(lh);
399925ca369SKent Gibson 	return ret;
400925ca369SKent Gibson }
401*3c0d9c63SKent Gibson #endif /* CONFIG_GPIO_CDEV_V1 */
402*3c0d9c63SKent Gibson 
403*3c0d9c63SKent Gibson /**
404*3c0d9c63SKent Gibson  * struct line - contains the state of a requested line
405*3c0d9c63SKent Gibson  * @desc: the GPIO descriptor for this line.
406*3c0d9c63SKent Gibson  */
407*3c0d9c63SKent Gibson struct line {
408*3c0d9c63SKent Gibson 	struct gpio_desc *desc;
409*3c0d9c63SKent Gibson };
410*3c0d9c63SKent Gibson 
411*3c0d9c63SKent Gibson /**
412*3c0d9c63SKent Gibson  * struct linereq - contains the state of a userspace line request
413*3c0d9c63SKent Gibson  * @gdev: the GPIO device the line request pertains to
414*3c0d9c63SKent Gibson  * @label: consumer label used to tag GPIO descriptors
415*3c0d9c63SKent Gibson  * @num_lines: the number of lines in the lines array
416*3c0d9c63SKent Gibson  * @lines: the lines held by this line request, with @num_lines elements.
417*3c0d9c63SKent Gibson  */
418*3c0d9c63SKent Gibson struct linereq {
419*3c0d9c63SKent Gibson 	struct gpio_device *gdev;
420*3c0d9c63SKent Gibson 	const char *label;
421*3c0d9c63SKent Gibson 	u32 num_lines;
422*3c0d9c63SKent Gibson 	struct line lines[];
423*3c0d9c63SKent Gibson };
424*3c0d9c63SKent Gibson 
425*3c0d9c63SKent Gibson #define GPIO_V2_LINE_BIAS_FLAGS \
426*3c0d9c63SKent Gibson 	(GPIO_V2_LINE_FLAG_BIAS_PULL_UP | \
427*3c0d9c63SKent Gibson 	 GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN | \
428*3c0d9c63SKent Gibson 	 GPIO_V2_LINE_FLAG_BIAS_DISABLED)
429*3c0d9c63SKent Gibson 
430*3c0d9c63SKent Gibson #define GPIO_V2_LINE_DIRECTION_FLAGS \
431*3c0d9c63SKent Gibson 	(GPIO_V2_LINE_FLAG_INPUT | \
432*3c0d9c63SKent Gibson 	 GPIO_V2_LINE_FLAG_OUTPUT)
433*3c0d9c63SKent Gibson 
434*3c0d9c63SKent Gibson #define GPIO_V2_LINE_DRIVE_FLAGS \
435*3c0d9c63SKent Gibson 	(GPIO_V2_LINE_FLAG_OPEN_DRAIN | \
436*3c0d9c63SKent Gibson 	 GPIO_V2_LINE_FLAG_OPEN_SOURCE)
437*3c0d9c63SKent Gibson 
438*3c0d9c63SKent Gibson #define GPIO_V2_LINE_VALID_FLAGS \
439*3c0d9c63SKent Gibson 	(GPIO_V2_LINE_FLAG_ACTIVE_LOW | \
440*3c0d9c63SKent Gibson 	 GPIO_V2_LINE_DIRECTION_FLAGS | \
441*3c0d9c63SKent Gibson 	 GPIO_V2_LINE_DRIVE_FLAGS | \
442*3c0d9c63SKent Gibson 	 GPIO_V2_LINE_BIAS_FLAGS)
443*3c0d9c63SKent Gibson 
444*3c0d9c63SKent Gibson static u64 gpio_v2_line_config_flags(struct gpio_v2_line_config *lc,
445*3c0d9c63SKent Gibson 				     unsigned int line_idx)
446*3c0d9c63SKent Gibson {
447*3c0d9c63SKent Gibson 	unsigned int i;
448*3c0d9c63SKent Gibson 	u64 mask = BIT_ULL(line_idx);
449*3c0d9c63SKent Gibson 
450*3c0d9c63SKent Gibson 	for (i = 0; i < lc->num_attrs; i++) {
451*3c0d9c63SKent Gibson 		if ((lc->attrs[i].attr.id == GPIO_V2_LINE_ATTR_ID_FLAGS) &&
452*3c0d9c63SKent Gibson 		    (lc->attrs[i].mask & mask))
453*3c0d9c63SKent Gibson 			return lc->attrs[i].attr.flags;
454*3c0d9c63SKent Gibson 	}
455*3c0d9c63SKent Gibson 	return lc->flags;
456*3c0d9c63SKent Gibson }
457*3c0d9c63SKent Gibson 
458*3c0d9c63SKent Gibson static int gpio_v2_line_config_output_value(struct gpio_v2_line_config *lc,
459*3c0d9c63SKent Gibson 					    unsigned int line_idx)
460*3c0d9c63SKent Gibson {
461*3c0d9c63SKent Gibson 	unsigned int i;
462*3c0d9c63SKent Gibson 	u64 mask = BIT_ULL(line_idx);
463*3c0d9c63SKent Gibson 
464*3c0d9c63SKent Gibson 	for (i = 0; i < lc->num_attrs; i++) {
465*3c0d9c63SKent Gibson 		if ((lc->attrs[i].attr.id == GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES) &&
466*3c0d9c63SKent Gibson 		    (lc->attrs[i].mask & mask))
467*3c0d9c63SKent Gibson 			return !!(lc->attrs[i].attr.values & mask);
468*3c0d9c63SKent Gibson 	}
469*3c0d9c63SKent Gibson 	return 0;
470*3c0d9c63SKent Gibson }
471*3c0d9c63SKent Gibson 
472*3c0d9c63SKent Gibson static int gpio_v2_line_flags_validate(u64 flags)
473*3c0d9c63SKent Gibson {
474*3c0d9c63SKent Gibson 	/* Return an error if an unknown flag is set */
475*3c0d9c63SKent Gibson 	if (flags & ~GPIO_V2_LINE_VALID_FLAGS)
476*3c0d9c63SKent Gibson 		return -EINVAL;
477*3c0d9c63SKent Gibson 
478*3c0d9c63SKent Gibson 	/*
479*3c0d9c63SKent Gibson 	 * Do not allow both INPUT and OUTPUT flags to be set as they are
480*3c0d9c63SKent Gibson 	 * contradictory.
481*3c0d9c63SKent Gibson 	 */
482*3c0d9c63SKent Gibson 	if ((flags & GPIO_V2_LINE_FLAG_INPUT) &&
483*3c0d9c63SKent Gibson 	    (flags & GPIO_V2_LINE_FLAG_OUTPUT))
484*3c0d9c63SKent Gibson 		return -EINVAL;
485*3c0d9c63SKent Gibson 
486*3c0d9c63SKent Gibson 	/*
487*3c0d9c63SKent Gibson 	 * Do not allow OPEN_SOURCE and OPEN_DRAIN flags in a single
488*3c0d9c63SKent Gibson 	 * request. If the hardware actually supports enabling both at the
489*3c0d9c63SKent Gibson 	 * same time the electrical result would be disastrous.
490*3c0d9c63SKent Gibson 	 */
491*3c0d9c63SKent Gibson 	if ((flags & GPIO_V2_LINE_FLAG_OPEN_DRAIN) &&
492*3c0d9c63SKent Gibson 	    (flags & GPIO_V2_LINE_FLAG_OPEN_SOURCE))
493*3c0d9c63SKent Gibson 		return -EINVAL;
494*3c0d9c63SKent Gibson 
495*3c0d9c63SKent Gibson 	/* Drive requires explicit output direction. */
496*3c0d9c63SKent Gibson 	if ((flags & GPIO_V2_LINE_DRIVE_FLAGS) &&
497*3c0d9c63SKent Gibson 	    !(flags & GPIO_V2_LINE_FLAG_OUTPUT))
498*3c0d9c63SKent Gibson 		return -EINVAL;
499*3c0d9c63SKent Gibson 
500*3c0d9c63SKent Gibson 	/* Bias requires explicit direction. */
501*3c0d9c63SKent Gibson 	if ((flags & GPIO_V2_LINE_BIAS_FLAGS) &&
502*3c0d9c63SKent Gibson 	    !(flags & GPIO_V2_LINE_DIRECTION_FLAGS))
503*3c0d9c63SKent Gibson 		return -EINVAL;
504*3c0d9c63SKent Gibson 
505*3c0d9c63SKent Gibson 	/* Only one bias flag can be set. */
506*3c0d9c63SKent Gibson 	if (((flags & GPIO_V2_LINE_FLAG_BIAS_DISABLED) &&
507*3c0d9c63SKent Gibson 	     (flags & (GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN |
508*3c0d9c63SKent Gibson 		       GPIO_V2_LINE_FLAG_BIAS_PULL_UP))) ||
509*3c0d9c63SKent Gibson 	    ((flags & GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN) &&
510*3c0d9c63SKent Gibson 	     (flags & GPIO_V2_LINE_FLAG_BIAS_PULL_UP)))
511*3c0d9c63SKent Gibson 		return -EINVAL;
512*3c0d9c63SKent Gibson 
513*3c0d9c63SKent Gibson 	return 0;
514*3c0d9c63SKent Gibson }
515*3c0d9c63SKent Gibson 
516*3c0d9c63SKent Gibson static int gpio_v2_line_config_validate(struct gpio_v2_line_config *lc,
517*3c0d9c63SKent Gibson 					unsigned int num_lines)
518*3c0d9c63SKent Gibson {
519*3c0d9c63SKent Gibson 	unsigned int i;
520*3c0d9c63SKent Gibson 	u64 flags;
521*3c0d9c63SKent Gibson 	int ret;
522*3c0d9c63SKent Gibson 
523*3c0d9c63SKent Gibson 	if (lc->num_attrs > GPIO_V2_LINE_NUM_ATTRS_MAX)
524*3c0d9c63SKent Gibson 		return -EINVAL;
525*3c0d9c63SKent Gibson 
526*3c0d9c63SKent Gibson 	if (memchr_inv(lc->padding, 0, sizeof(lc->padding)))
527*3c0d9c63SKent Gibson 		return -EINVAL;
528*3c0d9c63SKent Gibson 
529*3c0d9c63SKent Gibson 	for (i = 0; i < num_lines; i++) {
530*3c0d9c63SKent Gibson 		flags = gpio_v2_line_config_flags(lc, i);
531*3c0d9c63SKent Gibson 		ret = gpio_v2_line_flags_validate(flags);
532*3c0d9c63SKent Gibson 		if (ret)
533*3c0d9c63SKent Gibson 			return ret;
534*3c0d9c63SKent Gibson 	}
535*3c0d9c63SKent Gibson 	return 0;
536*3c0d9c63SKent Gibson }
537*3c0d9c63SKent Gibson 
538*3c0d9c63SKent Gibson static void gpio_v2_line_config_flags_to_desc_flags(u64 flags,
539*3c0d9c63SKent Gibson 						    unsigned long *flagsp)
540*3c0d9c63SKent Gibson {
541*3c0d9c63SKent Gibson 	assign_bit(FLAG_ACTIVE_LOW, flagsp,
542*3c0d9c63SKent Gibson 		   flags & GPIO_V2_LINE_FLAG_ACTIVE_LOW);
543*3c0d9c63SKent Gibson 
544*3c0d9c63SKent Gibson 	if (flags & GPIO_V2_LINE_FLAG_OUTPUT)
545*3c0d9c63SKent Gibson 		set_bit(FLAG_IS_OUT, flagsp);
546*3c0d9c63SKent Gibson 	else if (flags & GPIO_V2_LINE_FLAG_INPUT)
547*3c0d9c63SKent Gibson 		clear_bit(FLAG_IS_OUT, flagsp);
548*3c0d9c63SKent Gibson 
549*3c0d9c63SKent Gibson 	assign_bit(FLAG_OPEN_DRAIN, flagsp,
550*3c0d9c63SKent Gibson 		   flags & GPIO_V2_LINE_FLAG_OPEN_DRAIN);
551*3c0d9c63SKent Gibson 	assign_bit(FLAG_OPEN_SOURCE, flagsp,
552*3c0d9c63SKent Gibson 		   flags & GPIO_V2_LINE_FLAG_OPEN_SOURCE);
553*3c0d9c63SKent Gibson 
554*3c0d9c63SKent Gibson 	assign_bit(FLAG_PULL_UP, flagsp,
555*3c0d9c63SKent Gibson 		   flags & GPIO_V2_LINE_FLAG_BIAS_PULL_UP);
556*3c0d9c63SKent Gibson 	assign_bit(FLAG_PULL_DOWN, flagsp,
557*3c0d9c63SKent Gibson 		   flags & GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN);
558*3c0d9c63SKent Gibson 	assign_bit(FLAG_BIAS_DISABLE, flagsp,
559*3c0d9c63SKent Gibson 		   flags & GPIO_V2_LINE_FLAG_BIAS_DISABLED);
560*3c0d9c63SKent Gibson }
561*3c0d9c63SKent Gibson 
562*3c0d9c63SKent Gibson static long linereq_get_values(struct linereq *lr, void __user *ip)
563*3c0d9c63SKent Gibson {
564*3c0d9c63SKent Gibson 	struct gpio_v2_line_values lv;
565*3c0d9c63SKent Gibson 	DECLARE_BITMAP(vals, GPIO_V2_LINES_MAX);
566*3c0d9c63SKent Gibson 	struct gpio_desc **descs;
567*3c0d9c63SKent Gibson 	unsigned int i, didx, num_get;
568*3c0d9c63SKent Gibson 	int ret;
569*3c0d9c63SKent Gibson 
570*3c0d9c63SKent Gibson 	/* NOTE: It's ok to read values of output lines. */
571*3c0d9c63SKent Gibson 	if (copy_from_user(&lv, ip, sizeof(lv)))
572*3c0d9c63SKent Gibson 		return -EFAULT;
573*3c0d9c63SKent Gibson 
574*3c0d9c63SKent Gibson 	for (num_get = 0, i = 0; i < lr->num_lines; i++) {
575*3c0d9c63SKent Gibson 		if (lv.mask & BIT_ULL(i)) {
576*3c0d9c63SKent Gibson 			num_get++;
577*3c0d9c63SKent Gibson 			descs = &lr->lines[i].desc;
578*3c0d9c63SKent Gibson 		}
579*3c0d9c63SKent Gibson 	}
580*3c0d9c63SKent Gibson 
581*3c0d9c63SKent Gibson 	if (num_get == 0)
582*3c0d9c63SKent Gibson 		return -EINVAL;
583*3c0d9c63SKent Gibson 
584*3c0d9c63SKent Gibson 	if (num_get != 1) {
585*3c0d9c63SKent Gibson 		descs = kmalloc_array(num_get, sizeof(*descs), GFP_KERNEL);
586*3c0d9c63SKent Gibson 		if (!descs)
587*3c0d9c63SKent Gibson 			return -ENOMEM;
588*3c0d9c63SKent Gibson 		for (didx = 0, i = 0; i < lr->num_lines; i++) {
589*3c0d9c63SKent Gibson 			if (lv.mask & BIT_ULL(i)) {
590*3c0d9c63SKent Gibson 				descs[didx] = lr->lines[i].desc;
591*3c0d9c63SKent Gibson 				didx++;
592*3c0d9c63SKent Gibson 			}
593*3c0d9c63SKent Gibson 		}
594*3c0d9c63SKent Gibson 	}
595*3c0d9c63SKent Gibson 	ret = gpiod_get_array_value_complex(false, true, num_get,
596*3c0d9c63SKent Gibson 					    descs, NULL, vals);
597*3c0d9c63SKent Gibson 
598*3c0d9c63SKent Gibson 	if (num_get != 1)
599*3c0d9c63SKent Gibson 		kfree(descs);
600*3c0d9c63SKent Gibson 	if (ret)
601*3c0d9c63SKent Gibson 		return ret;
602*3c0d9c63SKent Gibson 
603*3c0d9c63SKent Gibson 	lv.bits = 0;
604*3c0d9c63SKent Gibson 	for (didx = 0, i = 0; i < lr->num_lines; i++) {
605*3c0d9c63SKent Gibson 		if (lv.mask & BIT_ULL(i)) {
606*3c0d9c63SKent Gibson 			if (test_bit(didx, vals))
607*3c0d9c63SKent Gibson 				lv.bits |= BIT_ULL(i);
608*3c0d9c63SKent Gibson 			didx++;
609*3c0d9c63SKent Gibson 		}
610*3c0d9c63SKent Gibson 	}
611*3c0d9c63SKent Gibson 
612*3c0d9c63SKent Gibson 	if (copy_to_user(ip, &lv, sizeof(lv)))
613*3c0d9c63SKent Gibson 		return -EFAULT;
614*3c0d9c63SKent Gibson 
615*3c0d9c63SKent Gibson 	return 0;
616*3c0d9c63SKent Gibson }
617*3c0d9c63SKent Gibson 
618*3c0d9c63SKent Gibson static long linereq_ioctl(struct file *file, unsigned int cmd,
619*3c0d9c63SKent Gibson 			  unsigned long arg)
620*3c0d9c63SKent Gibson {
621*3c0d9c63SKent Gibson 	struct linereq *lr = file->private_data;
622*3c0d9c63SKent Gibson 	void __user *ip = (void __user *)arg;
623*3c0d9c63SKent Gibson 
624*3c0d9c63SKent Gibson 	if (cmd == GPIO_V2_LINE_GET_VALUES_IOCTL)
625*3c0d9c63SKent Gibson 		return linereq_get_values(lr, ip);
626*3c0d9c63SKent Gibson 
627*3c0d9c63SKent Gibson 	return -EINVAL;
628*3c0d9c63SKent Gibson }
629*3c0d9c63SKent Gibson 
630*3c0d9c63SKent Gibson #ifdef CONFIG_COMPAT
631*3c0d9c63SKent Gibson static long linereq_ioctl_compat(struct file *file, unsigned int cmd,
632*3c0d9c63SKent Gibson 				 unsigned long arg)
633*3c0d9c63SKent Gibson {
634*3c0d9c63SKent Gibson 	return linereq_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
635*3c0d9c63SKent Gibson }
636*3c0d9c63SKent Gibson #endif
637*3c0d9c63SKent Gibson 
638*3c0d9c63SKent Gibson static void linereq_free(struct linereq *lr)
639*3c0d9c63SKent Gibson {
640*3c0d9c63SKent Gibson 	unsigned int i;
641*3c0d9c63SKent Gibson 
642*3c0d9c63SKent Gibson 	for (i = 0; i < lr->num_lines; i++) {
643*3c0d9c63SKent Gibson 		if (lr->lines[i].desc)
644*3c0d9c63SKent Gibson 			gpiod_free(lr->lines[i].desc);
645*3c0d9c63SKent Gibson 	}
646*3c0d9c63SKent Gibson 	kfree(lr->label);
647*3c0d9c63SKent Gibson 	put_device(&lr->gdev->dev);
648*3c0d9c63SKent Gibson 	kfree(lr);
649*3c0d9c63SKent Gibson }
650*3c0d9c63SKent Gibson 
651*3c0d9c63SKent Gibson static int linereq_release(struct inode *inode, struct file *file)
652*3c0d9c63SKent Gibson {
653*3c0d9c63SKent Gibson 	struct linereq *lr = file->private_data;
654*3c0d9c63SKent Gibson 
655*3c0d9c63SKent Gibson 	linereq_free(lr);
656*3c0d9c63SKent Gibson 	return 0;
657*3c0d9c63SKent Gibson }
658*3c0d9c63SKent Gibson 
659*3c0d9c63SKent Gibson static const struct file_operations line_fileops = {
660*3c0d9c63SKent Gibson 	.release = linereq_release,
661*3c0d9c63SKent Gibson 	.owner = THIS_MODULE,
662*3c0d9c63SKent Gibson 	.llseek = noop_llseek,
663*3c0d9c63SKent Gibson 	.unlocked_ioctl = linereq_ioctl,
664*3c0d9c63SKent Gibson #ifdef CONFIG_COMPAT
665*3c0d9c63SKent Gibson 	.compat_ioctl = linereq_ioctl_compat,
666*3c0d9c63SKent Gibson #endif
667*3c0d9c63SKent Gibson };
668*3c0d9c63SKent Gibson 
669*3c0d9c63SKent Gibson static int linereq_create(struct gpio_device *gdev, void __user *ip)
670*3c0d9c63SKent Gibson {
671*3c0d9c63SKent Gibson 	struct gpio_v2_line_request ulr;
672*3c0d9c63SKent Gibson 	struct gpio_v2_line_config *lc;
673*3c0d9c63SKent Gibson 	struct linereq *lr;
674*3c0d9c63SKent Gibson 	struct file *file;
675*3c0d9c63SKent Gibson 	u64 flags;
676*3c0d9c63SKent Gibson 	unsigned int i;
677*3c0d9c63SKent Gibson 	int fd, ret;
678*3c0d9c63SKent Gibson 
679*3c0d9c63SKent Gibson 	if (copy_from_user(&ulr, ip, sizeof(ulr)))
680*3c0d9c63SKent Gibson 		return -EFAULT;
681*3c0d9c63SKent Gibson 
682*3c0d9c63SKent Gibson 	if ((ulr.num_lines == 0) || (ulr.num_lines > GPIO_V2_LINES_MAX))
683*3c0d9c63SKent Gibson 		return -EINVAL;
684*3c0d9c63SKent Gibson 
685*3c0d9c63SKent Gibson 	if (memchr_inv(ulr.padding, 0, sizeof(ulr.padding)))
686*3c0d9c63SKent Gibson 		return -EINVAL;
687*3c0d9c63SKent Gibson 
688*3c0d9c63SKent Gibson 	lc = &ulr.config;
689*3c0d9c63SKent Gibson 	ret = gpio_v2_line_config_validate(lc, ulr.num_lines);
690*3c0d9c63SKent Gibson 	if (ret)
691*3c0d9c63SKent Gibson 		return ret;
692*3c0d9c63SKent Gibson 
693*3c0d9c63SKent Gibson 	lr = kzalloc(struct_size(lr, lines, ulr.num_lines), GFP_KERNEL);
694*3c0d9c63SKent Gibson 	if (!lr)
695*3c0d9c63SKent Gibson 		return -ENOMEM;
696*3c0d9c63SKent Gibson 
697*3c0d9c63SKent Gibson 	lr->gdev = gdev;
698*3c0d9c63SKent Gibson 	get_device(&gdev->dev);
699*3c0d9c63SKent Gibson 
700*3c0d9c63SKent Gibson 	/* Make sure this is terminated */
701*3c0d9c63SKent Gibson 	ulr.consumer[sizeof(ulr.consumer)-1] = '\0';
702*3c0d9c63SKent Gibson 	if (strlen(ulr.consumer)) {
703*3c0d9c63SKent Gibson 		/* label is only initialized if consumer is set */
704*3c0d9c63SKent Gibson 		lr->label = kstrdup(ulr.consumer, GFP_KERNEL);
705*3c0d9c63SKent Gibson 		if (!lr->label) {
706*3c0d9c63SKent Gibson 			ret = -ENOMEM;
707*3c0d9c63SKent Gibson 			goto out_free_linereq;
708*3c0d9c63SKent Gibson 		}
709*3c0d9c63SKent Gibson 	}
710*3c0d9c63SKent Gibson 
711*3c0d9c63SKent Gibson 	lr->num_lines = ulr.num_lines;
712*3c0d9c63SKent Gibson 
713*3c0d9c63SKent Gibson 	/* Request each GPIO */
714*3c0d9c63SKent Gibson 	for (i = 0; i < ulr.num_lines; i++) {
715*3c0d9c63SKent Gibson 		u32 offset = ulr.offsets[i];
716*3c0d9c63SKent Gibson 		struct gpio_desc *desc = gpiochip_get_desc(gdev->chip, offset);
717*3c0d9c63SKent Gibson 
718*3c0d9c63SKent Gibson 		if (IS_ERR(desc)) {
719*3c0d9c63SKent Gibson 			ret = PTR_ERR(desc);
720*3c0d9c63SKent Gibson 			goto out_free_linereq;
721*3c0d9c63SKent Gibson 		}
722*3c0d9c63SKent Gibson 
723*3c0d9c63SKent Gibson 		ret = gpiod_request(desc, lr->label);
724*3c0d9c63SKent Gibson 		if (ret)
725*3c0d9c63SKent Gibson 			goto out_free_linereq;
726*3c0d9c63SKent Gibson 
727*3c0d9c63SKent Gibson 		lr->lines[i].desc = desc;
728*3c0d9c63SKent Gibson 		flags = gpio_v2_line_config_flags(lc, i);
729*3c0d9c63SKent Gibson 		gpio_v2_line_config_flags_to_desc_flags(flags, &desc->flags);
730*3c0d9c63SKent Gibson 
731*3c0d9c63SKent Gibson 		ret = gpiod_set_transitory(desc, false);
732*3c0d9c63SKent Gibson 		if (ret < 0)
733*3c0d9c63SKent Gibson 			goto out_free_linereq;
734*3c0d9c63SKent Gibson 
735*3c0d9c63SKent Gibson 		/*
736*3c0d9c63SKent Gibson 		 * Lines have to be requested explicitly for input
737*3c0d9c63SKent Gibson 		 * or output, else the line will be treated "as is".
738*3c0d9c63SKent Gibson 		 */
739*3c0d9c63SKent Gibson 		if (flags & GPIO_V2_LINE_FLAG_OUTPUT) {
740*3c0d9c63SKent Gibson 			int val = gpio_v2_line_config_output_value(lc, i);
741*3c0d9c63SKent Gibson 
742*3c0d9c63SKent Gibson 			ret = gpiod_direction_output(desc, val);
743*3c0d9c63SKent Gibson 			if (ret)
744*3c0d9c63SKent Gibson 				goto out_free_linereq;
745*3c0d9c63SKent Gibson 		} else if (flags & GPIO_V2_LINE_FLAG_INPUT) {
746*3c0d9c63SKent Gibson 			ret = gpiod_direction_input(desc);
747*3c0d9c63SKent Gibson 			if (ret)
748*3c0d9c63SKent Gibson 				goto out_free_linereq;
749*3c0d9c63SKent Gibson 		}
750*3c0d9c63SKent Gibson 
751*3c0d9c63SKent Gibson 		blocking_notifier_call_chain(&desc->gdev->notifier,
752*3c0d9c63SKent Gibson 					     GPIOLINE_CHANGED_REQUESTED, desc);
753*3c0d9c63SKent Gibson 
754*3c0d9c63SKent Gibson 		dev_dbg(&gdev->dev, "registered chardev handle for line %d\n",
755*3c0d9c63SKent Gibson 			offset);
756*3c0d9c63SKent Gibson 	}
757*3c0d9c63SKent Gibson 
758*3c0d9c63SKent Gibson 	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
759*3c0d9c63SKent Gibson 	if (fd < 0) {
760*3c0d9c63SKent Gibson 		ret = fd;
761*3c0d9c63SKent Gibson 		goto out_free_linereq;
762*3c0d9c63SKent Gibson 	}
763*3c0d9c63SKent Gibson 
764*3c0d9c63SKent Gibson 	file = anon_inode_getfile("gpio-line", &line_fileops, lr,
765*3c0d9c63SKent Gibson 				  O_RDONLY | O_CLOEXEC);
766*3c0d9c63SKent Gibson 	if (IS_ERR(file)) {
767*3c0d9c63SKent Gibson 		ret = PTR_ERR(file);
768*3c0d9c63SKent Gibson 		goto out_put_unused_fd;
769*3c0d9c63SKent Gibson 	}
770*3c0d9c63SKent Gibson 
771*3c0d9c63SKent Gibson 	ulr.fd = fd;
772*3c0d9c63SKent Gibson 	if (copy_to_user(ip, &ulr, sizeof(ulr))) {
773*3c0d9c63SKent Gibson 		/*
774*3c0d9c63SKent Gibson 		 * fput() will trigger the release() callback, so do not go onto
775*3c0d9c63SKent Gibson 		 * the regular error cleanup path here.
776*3c0d9c63SKent Gibson 		 */
777*3c0d9c63SKent Gibson 		fput(file);
778*3c0d9c63SKent Gibson 		put_unused_fd(fd);
779*3c0d9c63SKent Gibson 		return -EFAULT;
780*3c0d9c63SKent Gibson 	}
781*3c0d9c63SKent Gibson 
782*3c0d9c63SKent Gibson 	fd_install(fd, file);
783*3c0d9c63SKent Gibson 
784*3c0d9c63SKent Gibson 	dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
785*3c0d9c63SKent Gibson 		lr->num_lines);
786*3c0d9c63SKent Gibson 
787*3c0d9c63SKent Gibson 	return 0;
788*3c0d9c63SKent Gibson 
789*3c0d9c63SKent Gibson out_put_unused_fd:
790*3c0d9c63SKent Gibson 	put_unused_fd(fd);
791*3c0d9c63SKent Gibson out_free_linereq:
792*3c0d9c63SKent Gibson 	linereq_free(lr);
793*3c0d9c63SKent Gibson 	return ret;
794*3c0d9c63SKent Gibson }
795*3c0d9c63SKent Gibson 
796*3c0d9c63SKent Gibson #ifdef CONFIG_GPIO_CDEV_V1
797925ca369SKent Gibson 
798925ca369SKent Gibson /*
799925ca369SKent Gibson  * GPIO line event management
800925ca369SKent Gibson  */
801925ca369SKent Gibson 
802925ca369SKent Gibson /**
803925ca369SKent Gibson  * struct lineevent_state - contains the state of a userspace event
804925ca369SKent Gibson  * @gdev: the GPIO device the event pertains to
805925ca369SKent Gibson  * @label: consumer label used to tag descriptors
806925ca369SKent Gibson  * @desc: the GPIO descriptor held by this event
807925ca369SKent Gibson  * @eflags: the event flags this line was requested with
808925ca369SKent Gibson  * @irq: the interrupt that trigger in response to events on this GPIO
809925ca369SKent Gibson  * @wait: wait queue that handles blocking reads of events
810925ca369SKent Gibson  * @events: KFIFO for the GPIO events
811925ca369SKent Gibson  * @timestamp: cache for the timestamp storing it between hardirq
812925ca369SKent Gibson  * and IRQ thread, used to bring the timestamp close to the actual
813925ca369SKent Gibson  * event
814925ca369SKent Gibson  */
815925ca369SKent Gibson struct lineevent_state {
816925ca369SKent Gibson 	struct gpio_device *gdev;
817925ca369SKent Gibson 	const char *label;
818925ca369SKent Gibson 	struct gpio_desc *desc;
819925ca369SKent Gibson 	u32 eflags;
820925ca369SKent Gibson 	int irq;
821925ca369SKent Gibson 	wait_queue_head_t wait;
822925ca369SKent Gibson 	DECLARE_KFIFO(events, struct gpioevent_data, 16);
823925ca369SKent Gibson 	u64 timestamp;
824925ca369SKent Gibson };
825925ca369SKent Gibson 
826925ca369SKent Gibson #define GPIOEVENT_REQUEST_VALID_FLAGS \
827925ca369SKent Gibson 	(GPIOEVENT_REQUEST_RISING_EDGE | \
828925ca369SKent Gibson 	GPIOEVENT_REQUEST_FALLING_EDGE)
829925ca369SKent Gibson 
83049bc5279SKent Gibson static __poll_t lineevent_poll(struct file *file,
831925ca369SKent Gibson 			       struct poll_table_struct *wait)
832925ca369SKent Gibson {
83349bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
834925ca369SKent Gibson 	__poll_t events = 0;
835925ca369SKent Gibson 
83649bc5279SKent Gibson 	poll_wait(file, &le->wait, wait);
837925ca369SKent Gibson 
838925ca369SKent Gibson 	if (!kfifo_is_empty_spinlocked_noirqsave(&le->events, &le->wait.lock))
839925ca369SKent Gibson 		events = EPOLLIN | EPOLLRDNORM;
840925ca369SKent Gibson 
841925ca369SKent Gibson 	return events;
842925ca369SKent Gibson }
843925ca369SKent Gibson 
844925ca369SKent Gibson 
84549bc5279SKent Gibson static ssize_t lineevent_read(struct file *file,
846925ca369SKent Gibson 			      char __user *buf,
847925ca369SKent Gibson 			      size_t count,
848925ca369SKent Gibson 			      loff_t *f_ps)
849925ca369SKent Gibson {
85049bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
851925ca369SKent Gibson 	struct gpioevent_data ge;
852925ca369SKent Gibson 	ssize_t bytes_read = 0;
853925ca369SKent Gibson 	int ret;
854925ca369SKent Gibson 
855925ca369SKent Gibson 	if (count < sizeof(ge))
856925ca369SKent Gibson 		return -EINVAL;
857925ca369SKent Gibson 
858925ca369SKent Gibson 	do {
859925ca369SKent Gibson 		spin_lock(&le->wait.lock);
860925ca369SKent Gibson 		if (kfifo_is_empty(&le->events)) {
861925ca369SKent Gibson 			if (bytes_read) {
862925ca369SKent Gibson 				spin_unlock(&le->wait.lock);
863925ca369SKent Gibson 				return bytes_read;
864925ca369SKent Gibson 			}
865925ca369SKent Gibson 
86649bc5279SKent Gibson 			if (file->f_flags & O_NONBLOCK) {
867925ca369SKent Gibson 				spin_unlock(&le->wait.lock);
868925ca369SKent Gibson 				return -EAGAIN;
869925ca369SKent Gibson 			}
870925ca369SKent Gibson 
871925ca369SKent Gibson 			ret = wait_event_interruptible_locked(le->wait,
872925ca369SKent Gibson 					!kfifo_is_empty(&le->events));
873925ca369SKent Gibson 			if (ret) {
874925ca369SKent Gibson 				spin_unlock(&le->wait.lock);
875925ca369SKent Gibson 				return ret;
876925ca369SKent Gibson 			}
877925ca369SKent Gibson 		}
878925ca369SKent Gibson 
879925ca369SKent Gibson 		ret = kfifo_out(&le->events, &ge, 1);
880925ca369SKent Gibson 		spin_unlock(&le->wait.lock);
881925ca369SKent Gibson 		if (ret != 1) {
882925ca369SKent Gibson 			/*
883925ca369SKent Gibson 			 * This should never happen - we were holding the lock
884925ca369SKent Gibson 			 * from the moment we learned the fifo is no longer
885925ca369SKent Gibson 			 * empty until now.
886925ca369SKent Gibson 			 */
887925ca369SKent Gibson 			ret = -EIO;
888925ca369SKent Gibson 			break;
889925ca369SKent Gibson 		}
890925ca369SKent Gibson 
891925ca369SKent Gibson 		if (copy_to_user(buf + bytes_read, &ge, sizeof(ge)))
892925ca369SKent Gibson 			return -EFAULT;
893925ca369SKent Gibson 		bytes_read += sizeof(ge);
894925ca369SKent Gibson 	} while (count >= bytes_read + sizeof(ge));
895925ca369SKent Gibson 
896925ca369SKent Gibson 	return bytes_read;
897925ca369SKent Gibson }
898925ca369SKent Gibson 
89946824272SKent Gibson static void lineevent_free(struct lineevent_state *le)
900925ca369SKent Gibson {
90146824272SKent Gibson 	if (le->irq)
902925ca369SKent Gibson 		free_irq(le->irq, le);
90346824272SKent Gibson 	if (le->desc)
904925ca369SKent Gibson 		gpiod_free(le->desc);
905925ca369SKent Gibson 	kfree(le->label);
90646824272SKent Gibson 	put_device(&le->gdev->dev);
907925ca369SKent Gibson 	kfree(le);
90846824272SKent Gibson }
90946824272SKent Gibson 
91046824272SKent Gibson static int lineevent_release(struct inode *inode, struct file *file)
91146824272SKent Gibson {
91246824272SKent Gibson 	lineevent_free(file->private_data);
913925ca369SKent Gibson 	return 0;
914925ca369SKent Gibson }
915925ca369SKent Gibson 
91649bc5279SKent Gibson static long lineevent_ioctl(struct file *file, unsigned int cmd,
917925ca369SKent Gibson 			    unsigned long arg)
918925ca369SKent Gibson {
91949bc5279SKent Gibson 	struct lineevent_state *le = file->private_data;
920925ca369SKent Gibson 	void __user *ip = (void __user *)arg;
921925ca369SKent Gibson 	struct gpiohandle_data ghd;
922925ca369SKent Gibson 
923925ca369SKent Gibson 	/*
924925ca369SKent Gibson 	 * We can get the value for an event line but not set it,
925925ca369SKent Gibson 	 * because it is input by definition.
926925ca369SKent Gibson 	 */
927925ca369SKent Gibson 	if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
928925ca369SKent Gibson 		int val;
929925ca369SKent Gibson 
930925ca369SKent Gibson 		memset(&ghd, 0, sizeof(ghd));
931925ca369SKent Gibson 
932925ca369SKent Gibson 		val = gpiod_get_value_cansleep(le->desc);
933925ca369SKent Gibson 		if (val < 0)
934925ca369SKent Gibson 			return val;
935925ca369SKent Gibson 		ghd.values[0] = val;
936925ca369SKent Gibson 
937925ca369SKent Gibson 		if (copy_to_user(ip, &ghd, sizeof(ghd)))
938925ca369SKent Gibson 			return -EFAULT;
939925ca369SKent Gibson 
940925ca369SKent Gibson 		return 0;
941925ca369SKent Gibson 	}
942925ca369SKent Gibson 	return -EINVAL;
943925ca369SKent Gibson }
944925ca369SKent Gibson 
945925ca369SKent Gibson #ifdef CONFIG_COMPAT
94649bc5279SKent Gibson static long lineevent_ioctl_compat(struct file *file, unsigned int cmd,
947925ca369SKent Gibson 				   unsigned long arg)
948925ca369SKent Gibson {
94949bc5279SKent Gibson 	return lineevent_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
950925ca369SKent Gibson }
951925ca369SKent Gibson #endif
952925ca369SKent Gibson 
953925ca369SKent Gibson static const struct file_operations lineevent_fileops = {
954925ca369SKent Gibson 	.release = lineevent_release,
955925ca369SKent Gibson 	.read = lineevent_read,
956925ca369SKent Gibson 	.poll = lineevent_poll,
957925ca369SKent Gibson 	.owner = THIS_MODULE,
958925ca369SKent Gibson 	.llseek = noop_llseek,
959925ca369SKent Gibson 	.unlocked_ioctl = lineevent_ioctl,
960925ca369SKent Gibson #ifdef CONFIG_COMPAT
961925ca369SKent Gibson 	.compat_ioctl = lineevent_ioctl_compat,
962925ca369SKent Gibson #endif
963925ca369SKent Gibson };
964925ca369SKent Gibson 
965925ca369SKent Gibson static irqreturn_t lineevent_irq_thread(int irq, void *p)
966925ca369SKent Gibson {
967925ca369SKent Gibson 	struct lineevent_state *le = p;
968925ca369SKent Gibson 	struct gpioevent_data ge;
969925ca369SKent Gibson 	int ret;
970925ca369SKent Gibson 
971925ca369SKent Gibson 	/* Do not leak kernel stack to userspace */
972925ca369SKent Gibson 	memset(&ge, 0, sizeof(ge));
973925ca369SKent Gibson 
974925ca369SKent Gibson 	/*
975925ca369SKent Gibson 	 * We may be running from a nested threaded interrupt in which case
976925ca369SKent Gibson 	 * we didn't get the timestamp from lineevent_irq_handler().
977925ca369SKent Gibson 	 */
978925ca369SKent Gibson 	if (!le->timestamp)
979925ca369SKent Gibson 		ge.timestamp = ktime_get_ns();
980925ca369SKent Gibson 	else
981925ca369SKent Gibson 		ge.timestamp = le->timestamp;
982925ca369SKent Gibson 
983925ca369SKent Gibson 	if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
984925ca369SKent Gibson 	    && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
985925ca369SKent Gibson 		int level = gpiod_get_value_cansleep(le->desc);
986925ca369SKent Gibson 
987925ca369SKent Gibson 		if (level)
988925ca369SKent Gibson 			/* Emit low-to-high event */
989925ca369SKent Gibson 			ge.id = GPIOEVENT_EVENT_RISING_EDGE;
990925ca369SKent Gibson 		else
991925ca369SKent Gibson 			/* Emit high-to-low event */
992925ca369SKent Gibson 			ge.id = GPIOEVENT_EVENT_FALLING_EDGE;
993925ca369SKent Gibson 	} else if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE) {
994925ca369SKent Gibson 		/* Emit low-to-high event */
995925ca369SKent Gibson 		ge.id = GPIOEVENT_EVENT_RISING_EDGE;
996925ca369SKent Gibson 	} else if (le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
997925ca369SKent Gibson 		/* Emit high-to-low event */
998925ca369SKent Gibson 		ge.id = GPIOEVENT_EVENT_FALLING_EDGE;
999925ca369SKent Gibson 	} else {
1000925ca369SKent Gibson 		return IRQ_NONE;
1001925ca369SKent Gibson 	}
1002925ca369SKent Gibson 
1003925ca369SKent Gibson 	ret = kfifo_in_spinlocked_noirqsave(&le->events, &ge,
1004925ca369SKent Gibson 					    1, &le->wait.lock);
1005925ca369SKent Gibson 	if (ret)
1006925ca369SKent Gibson 		wake_up_poll(&le->wait, EPOLLIN);
1007925ca369SKent Gibson 	else
1008925ca369SKent Gibson 		pr_debug_ratelimited("event FIFO is full - event dropped\n");
1009925ca369SKent Gibson 
1010925ca369SKent Gibson 	return IRQ_HANDLED;
1011925ca369SKent Gibson }
1012925ca369SKent Gibson 
1013925ca369SKent Gibson static irqreturn_t lineevent_irq_handler(int irq, void *p)
1014925ca369SKent Gibson {
1015925ca369SKent Gibson 	struct lineevent_state *le = p;
1016925ca369SKent Gibson 
1017925ca369SKent Gibson 	/*
1018925ca369SKent Gibson 	 * Just store the timestamp in hardirq context so we get it as
1019925ca369SKent Gibson 	 * close in time as possible to the actual event.
1020925ca369SKent Gibson 	 */
1021925ca369SKent Gibson 	le->timestamp = ktime_get_ns();
1022925ca369SKent Gibson 
1023925ca369SKent Gibson 	return IRQ_WAKE_THREAD;
1024925ca369SKent Gibson }
1025925ca369SKent Gibson 
1026925ca369SKent Gibson static int lineevent_create(struct gpio_device *gdev, void __user *ip)
1027925ca369SKent Gibson {
1028925ca369SKent Gibson 	struct gpioevent_request eventreq;
1029925ca369SKent Gibson 	struct lineevent_state *le;
1030925ca369SKent Gibson 	struct gpio_desc *desc;
1031925ca369SKent Gibson 	struct file *file;
1032925ca369SKent Gibson 	u32 offset;
1033925ca369SKent Gibson 	u32 lflags;
1034925ca369SKent Gibson 	u32 eflags;
1035925ca369SKent Gibson 	int fd;
1036925ca369SKent Gibson 	int ret;
103746824272SKent Gibson 	int irq, irqflags = 0;
1038925ca369SKent Gibson 
1039925ca369SKent Gibson 	if (copy_from_user(&eventreq, ip, sizeof(eventreq)))
1040925ca369SKent Gibson 		return -EFAULT;
1041925ca369SKent Gibson 
1042925ca369SKent Gibson 	offset = eventreq.lineoffset;
1043925ca369SKent Gibson 	lflags = eventreq.handleflags;
1044925ca369SKent Gibson 	eflags = eventreq.eventflags;
1045925ca369SKent Gibson 
1046925ca369SKent Gibson 	desc = gpiochip_get_desc(gdev->chip, offset);
1047925ca369SKent Gibson 	if (IS_ERR(desc))
1048925ca369SKent Gibson 		return PTR_ERR(desc);
1049925ca369SKent Gibson 
1050925ca369SKent Gibson 	/* Return an error if a unknown flag is set */
1051925ca369SKent Gibson 	if ((lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) ||
1052925ca369SKent Gibson 	    (eflags & ~GPIOEVENT_REQUEST_VALID_FLAGS))
1053925ca369SKent Gibson 		return -EINVAL;
1054925ca369SKent Gibson 
1055925ca369SKent Gibson 	/* This is just wrong: we don't look for events on output lines */
1056925ca369SKent Gibson 	if ((lflags & GPIOHANDLE_REQUEST_OUTPUT) ||
1057925ca369SKent Gibson 	    (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) ||
1058925ca369SKent Gibson 	    (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE))
1059925ca369SKent Gibson 		return -EINVAL;
1060925ca369SKent Gibson 
1061925ca369SKent Gibson 	/* Only one bias flag can be set. */
1062925ca369SKent Gibson 	if (((lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE) &&
1063925ca369SKent Gibson 	     (lflags & (GPIOHANDLE_REQUEST_BIAS_PULL_DOWN |
1064925ca369SKent Gibson 			GPIOHANDLE_REQUEST_BIAS_PULL_UP))) ||
1065925ca369SKent Gibson 	    ((lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) &&
1066925ca369SKent Gibson 	     (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP)))
1067925ca369SKent Gibson 		return -EINVAL;
1068925ca369SKent Gibson 
1069925ca369SKent Gibson 	le = kzalloc(sizeof(*le), GFP_KERNEL);
1070925ca369SKent Gibson 	if (!le)
1071925ca369SKent Gibson 		return -ENOMEM;
1072925ca369SKent Gibson 	le->gdev = gdev;
1073925ca369SKent Gibson 	get_device(&gdev->dev);
1074925ca369SKent Gibson 
1075925ca369SKent Gibson 	/* Make sure this is terminated */
1076925ca369SKent Gibson 	eventreq.consumer_label[sizeof(eventreq.consumer_label)-1] = '\0';
1077925ca369SKent Gibson 	if (strlen(eventreq.consumer_label)) {
1078925ca369SKent Gibson 		le->label = kstrdup(eventreq.consumer_label,
1079925ca369SKent Gibson 				    GFP_KERNEL);
1080925ca369SKent Gibson 		if (!le->label) {
1081925ca369SKent Gibson 			ret = -ENOMEM;
1082925ca369SKent Gibson 			goto out_free_le;
1083925ca369SKent Gibson 		}
1084925ca369SKent Gibson 	}
1085925ca369SKent Gibson 
1086925ca369SKent Gibson 	ret = gpiod_request(desc, le->label);
1087925ca369SKent Gibson 	if (ret)
108846824272SKent Gibson 		goto out_free_le;
1089925ca369SKent Gibson 	le->desc = desc;
1090925ca369SKent Gibson 	le->eflags = eflags;
1091925ca369SKent Gibson 
1092c274b58aSKent Gibson 	linehandle_flags_to_desc_flags(lflags, &desc->flags);
1093925ca369SKent Gibson 
1094925ca369SKent Gibson 	ret = gpiod_direction_input(desc);
1095925ca369SKent Gibson 	if (ret)
109646824272SKent Gibson 		goto out_free_le;
1097925ca369SKent Gibson 
10986accc376SKent Gibson 	blocking_notifier_call_chain(&desc->gdev->notifier,
1099925ca369SKent Gibson 				     GPIOLINE_CHANGED_REQUESTED, desc);
1100925ca369SKent Gibson 
110146824272SKent Gibson 	irq = gpiod_to_irq(desc);
110246824272SKent Gibson 	if (irq <= 0) {
1103925ca369SKent Gibson 		ret = -ENODEV;
110446824272SKent Gibson 		goto out_free_le;
1105925ca369SKent Gibson 	}
110646824272SKent Gibson 	le->irq = irq;
1107925ca369SKent Gibson 
1108925ca369SKent Gibson 	if (eflags & GPIOEVENT_REQUEST_RISING_EDGE)
1109925ca369SKent Gibson 		irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
1110925ca369SKent Gibson 			IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
1111925ca369SKent Gibson 	if (eflags & GPIOEVENT_REQUEST_FALLING_EDGE)
1112925ca369SKent Gibson 		irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ?
1113925ca369SKent Gibson 			IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
1114925ca369SKent Gibson 	irqflags |= IRQF_ONESHOT;
1115925ca369SKent Gibson 
1116925ca369SKent Gibson 	INIT_KFIFO(le->events);
1117925ca369SKent Gibson 	init_waitqueue_head(&le->wait);
1118925ca369SKent Gibson 
1119925ca369SKent Gibson 	/* Request a thread to read the events */
1120925ca369SKent Gibson 	ret = request_threaded_irq(le->irq,
1121925ca369SKent Gibson 				   lineevent_irq_handler,
1122925ca369SKent Gibson 				   lineevent_irq_thread,
1123925ca369SKent Gibson 				   irqflags,
1124925ca369SKent Gibson 				   le->label,
1125925ca369SKent Gibson 				   le);
1126925ca369SKent Gibson 	if (ret)
112746824272SKent Gibson 		goto out_free_le;
1128925ca369SKent Gibson 
1129925ca369SKent Gibson 	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
1130925ca369SKent Gibson 	if (fd < 0) {
1131925ca369SKent Gibson 		ret = fd;
113246824272SKent Gibson 		goto out_free_le;
1133925ca369SKent Gibson 	}
1134925ca369SKent Gibson 
1135925ca369SKent Gibson 	file = anon_inode_getfile("gpio-event",
1136925ca369SKent Gibson 				  &lineevent_fileops,
1137925ca369SKent Gibson 				  le,
1138925ca369SKent Gibson 				  O_RDONLY | O_CLOEXEC);
1139925ca369SKent Gibson 	if (IS_ERR(file)) {
1140925ca369SKent Gibson 		ret = PTR_ERR(file);
1141925ca369SKent Gibson 		goto out_put_unused_fd;
1142925ca369SKent Gibson 	}
1143925ca369SKent Gibson 
1144925ca369SKent Gibson 	eventreq.fd = fd;
1145925ca369SKent Gibson 	if (copy_to_user(ip, &eventreq, sizeof(eventreq))) {
1146925ca369SKent Gibson 		/*
1147925ca369SKent Gibson 		 * fput() will trigger the release() callback, so do not go onto
1148925ca369SKent Gibson 		 * the regular error cleanup path here.
1149925ca369SKent Gibson 		 */
1150925ca369SKent Gibson 		fput(file);
1151925ca369SKent Gibson 		put_unused_fd(fd);
1152925ca369SKent Gibson 		return -EFAULT;
1153925ca369SKent Gibson 	}
1154925ca369SKent Gibson 
1155925ca369SKent Gibson 	fd_install(fd, file);
1156925ca369SKent Gibson 
1157925ca369SKent Gibson 	return 0;
1158925ca369SKent Gibson 
1159925ca369SKent Gibson out_put_unused_fd:
1160925ca369SKent Gibson 	put_unused_fd(fd);
1161925ca369SKent Gibson out_free_le:
116246824272SKent Gibson 	lineevent_free(le);
1163925ca369SKent Gibson 	return ret;
1164925ca369SKent Gibson }
1165925ca369SKent Gibson 
1166*3c0d9c63SKent Gibson #endif /* CONFIG_GPIO_CDEV_V1 */
1167*3c0d9c63SKent Gibson 
1168925ca369SKent Gibson static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
1169925ca369SKent Gibson 				  struct gpioline_info *info)
1170925ca369SKent Gibson {
1171925ca369SKent Gibson 	struct gpio_chip *gc = desc->gdev->chip;
1172925ca369SKent Gibson 	bool ok_for_pinctrl;
1173925ca369SKent Gibson 	unsigned long flags;
1174925ca369SKent Gibson 
117569e4e136SKent Gibson 	memset(info, 0, sizeof(*info));
11760dc11e3aSKent Gibson 	info->line_offset = gpio_chip_hwgpio(desc);
11770dc11e3aSKent Gibson 
1178925ca369SKent Gibson 	/*
1179925ca369SKent Gibson 	 * This function takes a mutex so we must check this before taking
1180925ca369SKent Gibson 	 * the spinlock.
1181925ca369SKent Gibson 	 *
1182925ca369SKent Gibson 	 * FIXME: find a non-racy way to retrieve this information. Maybe a
1183925ca369SKent Gibson 	 * lock common to both frameworks?
1184925ca369SKent Gibson 	 */
1185925ca369SKent Gibson 	ok_for_pinctrl =
1186925ca369SKent Gibson 		pinctrl_gpio_can_use_line(gc->base + info->line_offset);
1187925ca369SKent Gibson 
1188925ca369SKent Gibson 	spin_lock_irqsave(&gpio_lock, flags);
1189925ca369SKent Gibson 
119069e4e136SKent Gibson 	if (desc->name)
119169e4e136SKent Gibson 		strscpy(info->name, desc->name, sizeof(info->name));
1192925ca369SKent Gibson 
119369e4e136SKent Gibson 	if (desc->label)
119469e4e136SKent Gibson 		strscpy(info->consumer, desc->label, sizeof(info->consumer));
1195925ca369SKent Gibson 
1196925ca369SKent Gibson 	/*
1197925ca369SKent Gibson 	 * Userspace only need to know that the kernel is using this GPIO so
1198925ca369SKent Gibson 	 * it can't use it.
1199925ca369SKent Gibson 	 */
1200925ca369SKent Gibson 	info->flags = 0;
1201925ca369SKent Gibson 	if (test_bit(FLAG_REQUESTED, &desc->flags) ||
1202925ca369SKent Gibson 	    test_bit(FLAG_IS_HOGGED, &desc->flags) ||
1203925ca369SKent Gibson 	    test_bit(FLAG_USED_AS_IRQ, &desc->flags) ||
1204925ca369SKent Gibson 	    test_bit(FLAG_EXPORT, &desc->flags) ||
1205925ca369SKent Gibson 	    test_bit(FLAG_SYSFS, &desc->flags) ||
1206925ca369SKent Gibson 	    !ok_for_pinctrl)
1207925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_KERNEL;
1208925ca369SKent Gibson 	if (test_bit(FLAG_IS_OUT, &desc->flags))
1209925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_IS_OUT;
1210925ca369SKent Gibson 	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
1211925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_ACTIVE_LOW;
1212925ca369SKent Gibson 	if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
1213925ca369SKent Gibson 		info->flags |= (GPIOLINE_FLAG_OPEN_DRAIN |
1214925ca369SKent Gibson 				GPIOLINE_FLAG_IS_OUT);
1215925ca369SKent Gibson 	if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
1216925ca369SKent Gibson 		info->flags |= (GPIOLINE_FLAG_OPEN_SOURCE |
1217925ca369SKent Gibson 				GPIOLINE_FLAG_IS_OUT);
1218925ca369SKent Gibson 	if (test_bit(FLAG_BIAS_DISABLE, &desc->flags))
1219925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_BIAS_DISABLE;
1220925ca369SKent Gibson 	if (test_bit(FLAG_PULL_DOWN, &desc->flags))
1221925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN;
1222925ca369SKent Gibson 	if (test_bit(FLAG_PULL_UP, &desc->flags))
1223925ca369SKent Gibson 		info->flags |= GPIOLINE_FLAG_BIAS_PULL_UP;
1224925ca369SKent Gibson 
1225925ca369SKent Gibson 	spin_unlock_irqrestore(&gpio_lock, flags);
1226925ca369SKent Gibson }
1227925ca369SKent Gibson 
1228925ca369SKent Gibson struct gpio_chardev_data {
1229925ca369SKent Gibson 	struct gpio_device *gdev;
1230925ca369SKent Gibson 	wait_queue_head_t wait;
1231925ca369SKent Gibson 	DECLARE_KFIFO(events, struct gpioline_info_changed, 32);
1232925ca369SKent Gibson 	struct notifier_block lineinfo_changed_nb;
1233925ca369SKent Gibson 	unsigned long *watched_lines;
1234925ca369SKent Gibson };
1235925ca369SKent Gibson 
1236925ca369SKent Gibson /*
1237925ca369SKent Gibson  * gpio_ioctl() - ioctl handler for the GPIO chardev
1238925ca369SKent Gibson  */
123949bc5279SKent Gibson static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1240925ca369SKent Gibson {
1241e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
1242e2b781c5SKent Gibson 	struct gpio_device *gdev = cdev->gdev;
1243925ca369SKent Gibson 	struct gpio_chip *gc = gdev->chip;
1244925ca369SKent Gibson 	void __user *ip = (void __user *)arg;
1245925ca369SKent Gibson 	struct gpio_desc *desc;
1246925ca369SKent Gibson 	__u32 offset;
1247925ca369SKent Gibson 
1248925ca369SKent Gibson 	/* We fail any subsequent ioctl():s when the chip is gone */
1249925ca369SKent Gibson 	if (!gc)
1250925ca369SKent Gibson 		return -ENODEV;
1251925ca369SKent Gibson 
1252925ca369SKent Gibson 	/* Fill in the struct and pass to userspace */
1253925ca369SKent Gibson 	if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
1254925ca369SKent Gibson 		struct gpiochip_info chipinfo;
1255925ca369SKent Gibson 
1256925ca369SKent Gibson 		memset(&chipinfo, 0, sizeof(chipinfo));
1257925ca369SKent Gibson 
125869e4e136SKent Gibson 		strscpy(chipinfo.name, dev_name(&gdev->dev),
1259925ca369SKent Gibson 			sizeof(chipinfo.name));
126069e4e136SKent Gibson 		strscpy(chipinfo.label, gdev->label,
1261925ca369SKent Gibson 			sizeof(chipinfo.label));
1262925ca369SKent Gibson 		chipinfo.lines = gdev->ngpio;
1263925ca369SKent Gibson 		if (copy_to_user(ip, &chipinfo, sizeof(chipinfo)))
1264925ca369SKent Gibson 			return -EFAULT;
1265925ca369SKent Gibson 		return 0;
1266*3c0d9c63SKent Gibson #ifdef CONFIG_GPIO_CDEV_V1
1267925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEINFO_IOCTL) {
1268925ca369SKent Gibson 		struct gpioline_info lineinfo;
1269925ca369SKent Gibson 
1270925ca369SKent Gibson 		if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
1271925ca369SKent Gibson 			return -EFAULT;
1272925ca369SKent Gibson 
12731bf7ba40SKent Gibson 		/* this doubles as a range check on line_offset */
1274925ca369SKent Gibson 		desc = gpiochip_get_desc(gc, lineinfo.line_offset);
1275925ca369SKent Gibson 		if (IS_ERR(desc))
1276925ca369SKent Gibson 			return PTR_ERR(desc);
1277925ca369SKent Gibson 
1278925ca369SKent Gibson 		gpio_desc_to_lineinfo(desc, &lineinfo);
1279925ca369SKent Gibson 
1280925ca369SKent Gibson 		if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
1281925ca369SKent Gibson 			return -EFAULT;
1282925ca369SKent Gibson 		return 0;
1283925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
1284925ca369SKent Gibson 		return linehandle_create(gdev, ip);
1285925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEEVENT_IOCTL) {
1286925ca369SKent Gibson 		return lineevent_create(gdev, ip);
1287925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) {
1288925ca369SKent Gibson 		struct gpioline_info lineinfo;
1289925ca369SKent Gibson 
1290925ca369SKent Gibson 		if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
1291925ca369SKent Gibson 			return -EFAULT;
1292925ca369SKent Gibson 
12931bf7ba40SKent Gibson 		/* this doubles as a range check on line_offset */
1294925ca369SKent Gibson 		desc = gpiochip_get_desc(gc, lineinfo.line_offset);
1295925ca369SKent Gibson 		if (IS_ERR(desc))
1296925ca369SKent Gibson 			return PTR_ERR(desc);
1297925ca369SKent Gibson 
12981bf7ba40SKent Gibson 		if (test_and_set_bit(lineinfo.line_offset, cdev->watched_lines))
1299925ca369SKent Gibson 			return -EBUSY;
1300925ca369SKent Gibson 
1301925ca369SKent Gibson 		gpio_desc_to_lineinfo(desc, &lineinfo);
1302925ca369SKent Gibson 
1303f30ef3e8SKent Gibson 		if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) {
13041bf7ba40SKent Gibson 			clear_bit(lineinfo.line_offset, cdev->watched_lines);
1305925ca369SKent Gibson 			return -EFAULT;
1306f30ef3e8SKent Gibson 		}
1307925ca369SKent Gibson 
1308925ca369SKent Gibson 		return 0;
1309*3c0d9c63SKent Gibson #endif /* CONFIG_GPIO_CDEV_V1 */
1310*3c0d9c63SKent Gibson 	} else if (cmd == GPIO_V2_GET_LINE_IOCTL) {
1311*3c0d9c63SKent Gibson 		return linereq_create(gdev, ip);
1312925ca369SKent Gibson 	} else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) {
1313925ca369SKent Gibson 		if (copy_from_user(&offset, ip, sizeof(offset)))
1314925ca369SKent Gibson 			return -EFAULT;
1315925ca369SKent Gibson 
13161bf7ba40SKent Gibson 		if (offset >= cdev->gdev->ngpio)
13171bf7ba40SKent Gibson 			return -EINVAL;
1318925ca369SKent Gibson 
13191bf7ba40SKent Gibson 		if (!test_and_clear_bit(offset, cdev->watched_lines))
1320925ca369SKent Gibson 			return -EBUSY;
1321925ca369SKent Gibson 
1322925ca369SKent Gibson 		return 0;
1323925ca369SKent Gibson 	}
1324925ca369SKent Gibson 	return -EINVAL;
1325925ca369SKent Gibson }
1326925ca369SKent Gibson 
1327925ca369SKent Gibson #ifdef CONFIG_COMPAT
132849bc5279SKent Gibson static long gpio_ioctl_compat(struct file *file, unsigned int cmd,
1329925ca369SKent Gibson 			      unsigned long arg)
1330925ca369SKent Gibson {
133149bc5279SKent Gibson 	return gpio_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
1332925ca369SKent Gibson }
1333925ca369SKent Gibson #endif
1334925ca369SKent Gibson 
1335925ca369SKent Gibson static struct gpio_chardev_data *
1336925ca369SKent Gibson to_gpio_chardev_data(struct notifier_block *nb)
1337925ca369SKent Gibson {
1338925ca369SKent Gibson 	return container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb);
1339925ca369SKent Gibson }
1340925ca369SKent Gibson 
1341925ca369SKent Gibson static int lineinfo_changed_notify(struct notifier_block *nb,
1342925ca369SKent Gibson 				   unsigned long action, void *data)
1343925ca369SKent Gibson {
1344e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = to_gpio_chardev_data(nb);
1345925ca369SKent Gibson 	struct gpioline_info_changed chg;
1346925ca369SKent Gibson 	struct gpio_desc *desc = data;
1347925ca369SKent Gibson 	int ret;
1348925ca369SKent Gibson 
1349e2b781c5SKent Gibson 	if (!test_bit(gpio_chip_hwgpio(desc), cdev->watched_lines))
1350925ca369SKent Gibson 		return NOTIFY_DONE;
1351925ca369SKent Gibson 
1352925ca369SKent Gibson 	memset(&chg, 0, sizeof(chg));
1353925ca369SKent Gibson 	chg.event_type = action;
1354925ca369SKent Gibson 	chg.timestamp = ktime_get_ns();
1355925ca369SKent Gibson 	gpio_desc_to_lineinfo(desc, &chg.info);
1356925ca369SKent Gibson 
1357e2b781c5SKent Gibson 	ret = kfifo_in_spinlocked(&cdev->events, &chg, 1, &cdev->wait.lock);
1358925ca369SKent Gibson 	if (ret)
1359e2b781c5SKent Gibson 		wake_up_poll(&cdev->wait, EPOLLIN);
1360925ca369SKent Gibson 	else
1361925ca369SKent Gibson 		pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n");
1362925ca369SKent Gibson 
1363925ca369SKent Gibson 	return NOTIFY_OK;
1364925ca369SKent Gibson }
1365925ca369SKent Gibson 
136649bc5279SKent Gibson static __poll_t lineinfo_watch_poll(struct file *file,
1367925ca369SKent Gibson 				    struct poll_table_struct *pollt)
1368925ca369SKent Gibson {
1369e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
1370925ca369SKent Gibson 	__poll_t events = 0;
1371925ca369SKent Gibson 
1372e2b781c5SKent Gibson 	poll_wait(file, &cdev->wait, pollt);
1373925ca369SKent Gibson 
1374e2b781c5SKent Gibson 	if (!kfifo_is_empty_spinlocked_noirqsave(&cdev->events,
1375e2b781c5SKent Gibson 						 &cdev->wait.lock))
1376925ca369SKent Gibson 		events = EPOLLIN | EPOLLRDNORM;
1377925ca369SKent Gibson 
1378925ca369SKent Gibson 	return events;
1379925ca369SKent Gibson }
1380925ca369SKent Gibson 
138149bc5279SKent Gibson static ssize_t lineinfo_watch_read(struct file *file, char __user *buf,
1382925ca369SKent Gibson 				   size_t count, loff_t *off)
1383925ca369SKent Gibson {
1384e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
1385925ca369SKent Gibson 	struct gpioline_info_changed event;
1386925ca369SKent Gibson 	ssize_t bytes_read = 0;
1387925ca369SKent Gibson 	int ret;
1388925ca369SKent Gibson 
1389925ca369SKent Gibson 	if (count < sizeof(event))
1390925ca369SKent Gibson 		return -EINVAL;
1391925ca369SKent Gibson 
1392925ca369SKent Gibson 	do {
1393e2b781c5SKent Gibson 		spin_lock(&cdev->wait.lock);
1394e2b781c5SKent Gibson 		if (kfifo_is_empty(&cdev->events)) {
1395925ca369SKent Gibson 			if (bytes_read) {
1396e2b781c5SKent Gibson 				spin_unlock(&cdev->wait.lock);
1397925ca369SKent Gibson 				return bytes_read;
1398925ca369SKent Gibson 			}
1399925ca369SKent Gibson 
140049bc5279SKent Gibson 			if (file->f_flags & O_NONBLOCK) {
1401e2b781c5SKent Gibson 				spin_unlock(&cdev->wait.lock);
1402925ca369SKent Gibson 				return -EAGAIN;
1403925ca369SKent Gibson 			}
1404925ca369SKent Gibson 
1405e2b781c5SKent Gibson 			ret = wait_event_interruptible_locked(cdev->wait,
1406e2b781c5SKent Gibson 					!kfifo_is_empty(&cdev->events));
1407925ca369SKent Gibson 			if (ret) {
1408e2b781c5SKent Gibson 				spin_unlock(&cdev->wait.lock);
1409925ca369SKent Gibson 				return ret;
1410925ca369SKent Gibson 			}
1411925ca369SKent Gibson 		}
1412925ca369SKent Gibson 
1413e2b781c5SKent Gibson 		ret = kfifo_out(&cdev->events, &event, 1);
1414e2b781c5SKent Gibson 		spin_unlock(&cdev->wait.lock);
1415925ca369SKent Gibson 		if (ret != 1) {
1416925ca369SKent Gibson 			ret = -EIO;
1417925ca369SKent Gibson 			break;
1418925ca369SKent Gibson 			/* We should never get here. See lineevent_read(). */
1419925ca369SKent Gibson 		}
1420925ca369SKent Gibson 
1421925ca369SKent Gibson 		if (copy_to_user(buf + bytes_read, &event, sizeof(event)))
1422925ca369SKent Gibson 			return -EFAULT;
1423925ca369SKent Gibson 		bytes_read += sizeof(event);
1424925ca369SKent Gibson 	} while (count >= bytes_read + sizeof(event));
1425925ca369SKent Gibson 
1426925ca369SKent Gibson 	return bytes_read;
1427925ca369SKent Gibson }
1428925ca369SKent Gibson 
1429925ca369SKent Gibson /**
1430925ca369SKent Gibson  * gpio_chrdev_open() - open the chardev for ioctl operations
1431925ca369SKent Gibson  * @inode: inode for this chardev
143249bc5279SKent Gibson  * @file: file struct for storing private data
1433925ca369SKent Gibson  * Returns 0 on success
1434925ca369SKent Gibson  */
143549bc5279SKent Gibson static int gpio_chrdev_open(struct inode *inode, struct file *file)
1436925ca369SKent Gibson {
1437925ca369SKent Gibson 	struct gpio_device *gdev = container_of(inode->i_cdev,
1438925ca369SKent Gibson 						struct gpio_device, chrdev);
1439e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev;
1440925ca369SKent Gibson 	int ret = -ENOMEM;
1441925ca369SKent Gibson 
1442925ca369SKent Gibson 	/* Fail on open if the backing gpiochip is gone */
1443925ca369SKent Gibson 	if (!gdev->chip)
1444925ca369SKent Gibson 		return -ENODEV;
1445925ca369SKent Gibson 
1446e2b781c5SKent Gibson 	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
1447e2b781c5SKent Gibson 	if (!cdev)
1448925ca369SKent Gibson 		return -ENOMEM;
1449925ca369SKent Gibson 
1450e2b781c5SKent Gibson 	cdev->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL);
1451e2b781c5SKent Gibson 	if (!cdev->watched_lines)
1452e2b781c5SKent Gibson 		goto out_free_cdev;
1453925ca369SKent Gibson 
1454e2b781c5SKent Gibson 	init_waitqueue_head(&cdev->wait);
1455e2b781c5SKent Gibson 	INIT_KFIFO(cdev->events);
1456e2b781c5SKent Gibson 	cdev->gdev = gdev;
1457925ca369SKent Gibson 
1458e2b781c5SKent Gibson 	cdev->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify;
14596accc376SKent Gibson 	ret = blocking_notifier_chain_register(&gdev->notifier,
1460e2b781c5SKent Gibson 					       &cdev->lineinfo_changed_nb);
1461925ca369SKent Gibson 	if (ret)
1462925ca369SKent Gibson 		goto out_free_bitmap;
1463925ca369SKent Gibson 
1464925ca369SKent Gibson 	get_device(&gdev->dev);
1465e2b781c5SKent Gibson 	file->private_data = cdev;
1466925ca369SKent Gibson 
146749bc5279SKent Gibson 	ret = nonseekable_open(inode, file);
1468925ca369SKent Gibson 	if (ret)
1469925ca369SKent Gibson 		goto out_unregister_notifier;
1470925ca369SKent Gibson 
1471925ca369SKent Gibson 	return ret;
1472925ca369SKent Gibson 
1473925ca369SKent Gibson out_unregister_notifier:
14746accc376SKent Gibson 	blocking_notifier_chain_unregister(&gdev->notifier,
1475e2b781c5SKent Gibson 					   &cdev->lineinfo_changed_nb);
1476925ca369SKent Gibson out_free_bitmap:
1477e2b781c5SKent Gibson 	bitmap_free(cdev->watched_lines);
1478e2b781c5SKent Gibson out_free_cdev:
1479e2b781c5SKent Gibson 	kfree(cdev);
1480925ca369SKent Gibson 	return ret;
1481925ca369SKent Gibson }
1482925ca369SKent Gibson 
1483925ca369SKent Gibson /**
1484925ca369SKent Gibson  * gpio_chrdev_release() - close chardev after ioctl operations
1485925ca369SKent Gibson  * @inode: inode for this chardev
148649bc5279SKent Gibson  * @file: file struct for storing private data
1487925ca369SKent Gibson  * Returns 0 on success
1488925ca369SKent Gibson  */
148949bc5279SKent Gibson static int gpio_chrdev_release(struct inode *inode, struct file *file)
1490925ca369SKent Gibson {
1491e2b781c5SKent Gibson 	struct gpio_chardev_data *cdev = file->private_data;
1492e2b781c5SKent Gibson 	struct gpio_device *gdev = cdev->gdev;
1493925ca369SKent Gibson 
1494e2b781c5SKent Gibson 	bitmap_free(cdev->watched_lines);
14956accc376SKent Gibson 	blocking_notifier_chain_unregister(&gdev->notifier,
1496e2b781c5SKent Gibson 					   &cdev->lineinfo_changed_nb);
1497925ca369SKent Gibson 	put_device(&gdev->dev);
1498e2b781c5SKent Gibson 	kfree(cdev);
1499925ca369SKent Gibson 
1500925ca369SKent Gibson 	return 0;
1501925ca369SKent Gibson }
1502925ca369SKent Gibson 
1503925ca369SKent Gibson static const struct file_operations gpio_fileops = {
1504925ca369SKent Gibson 	.release = gpio_chrdev_release,
1505925ca369SKent Gibson 	.open = gpio_chrdev_open,
1506925ca369SKent Gibson 	.poll = lineinfo_watch_poll,
1507925ca369SKent Gibson 	.read = lineinfo_watch_read,
1508925ca369SKent Gibson 	.owner = THIS_MODULE,
1509925ca369SKent Gibson 	.llseek = no_llseek,
1510925ca369SKent Gibson 	.unlocked_ioctl = gpio_ioctl,
1511925ca369SKent Gibson #ifdef CONFIG_COMPAT
1512925ca369SKent Gibson 	.compat_ioctl = gpio_ioctl_compat,
1513925ca369SKent Gibson #endif
1514925ca369SKent Gibson };
1515925ca369SKent Gibson 
1516925ca369SKent Gibson int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt)
1517925ca369SKent Gibson {
1518925ca369SKent Gibson 	int ret;
1519925ca369SKent Gibson 
1520925ca369SKent Gibson 	cdev_init(&gdev->chrdev, &gpio_fileops);
1521925ca369SKent Gibson 	gdev->chrdev.owner = THIS_MODULE;
1522925ca369SKent Gibson 	gdev->dev.devt = MKDEV(MAJOR(devt), gdev->id);
1523925ca369SKent Gibson 
1524925ca369SKent Gibson 	ret = cdev_device_add(&gdev->chrdev, &gdev->dev);
1525925ca369SKent Gibson 	if (ret)
1526925ca369SKent Gibson 		return ret;
1527925ca369SKent Gibson 
1528925ca369SKent Gibson 	chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n",
1529925ca369SKent Gibson 		 MAJOR(devt), gdev->id);
1530925ca369SKent Gibson 
1531925ca369SKent Gibson 	return 0;
1532925ca369SKent Gibson }
1533925ca369SKent Gibson 
1534925ca369SKent Gibson void gpiolib_cdev_unregister(struct gpio_device *gdev)
1535925ca369SKent Gibson {
1536925ca369SKent Gibson 	cdev_device_del(&gdev->chrdev, &gdev->dev);
1537925ca369SKent Gibson }
1538