Commit | Line | Data |
---|---|---|
925ca369 KG |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | ||
3 | #include <linux/bitmap.h> | |
4 | #include <linux/kernel.h> | |
5 | #include <linux/module.h> | |
6 | #include <linux/interrupt.h> | |
7 | #include <linux/irqreturn.h> | |
8 | #include <linux/spinlock.h> | |
9 | #include <linux/device.h> | |
10 | #include <linux/err.h> | |
11 | #include <linux/gpio.h> | |
12 | #include <linux/gpio/driver.h> | |
13 | #include <linux/pinctrl/consumer.h> | |
14 | #include <linux/cdev.h> | |
15 | #include <linux/uaccess.h> | |
16 | #include <linux/compat.h> | |
17 | #include <linux/anon_inodes.h> | |
18 | #include <linux/file.h> | |
19 | #include <linux/kfifo.h> | |
20 | #include <linux/poll.h> | |
21 | #include <linux/timekeeping.h> | |
22 | #include <uapi/linux/gpio.h> | |
23 | ||
24 | #include "gpiolib.h" | |
25 | #include "gpiolib-cdev.h" | |
26 | ||
27 | /* Character device interface to GPIO. | |
28 | * | |
29 | * The GPIO character device, /dev/gpiochipN, provides userspace an | |
30 | * interface to gpiolib GPIOs via ioctl()s. | |
31 | */ | |
32 | ||
33 | /* | |
34 | * GPIO line handle management | |
35 | */ | |
36 | ||
37 | /** | |
38 | * struct linehandle_state - contains the state of a userspace handle | |
39 | * @gdev: the GPIO device the handle pertains to | |
40 | * @label: consumer label used to tag descriptors | |
41 | * @descs: the GPIO descriptors held by this handle | |
42 | * @numdescs: the number of descriptors held in the descs array | |
43 | */ | |
44 | struct linehandle_state { | |
45 | struct gpio_device *gdev; | |
46 | const char *label; | |
47 | struct gpio_desc *descs[GPIOHANDLES_MAX]; | |
48 | u32 numdescs; | |
49 | }; | |
50 | ||
51 | #define GPIOHANDLE_REQUEST_VALID_FLAGS \ | |
52 | (GPIOHANDLE_REQUEST_INPUT | \ | |
53 | GPIOHANDLE_REQUEST_OUTPUT | \ | |
54 | GPIOHANDLE_REQUEST_ACTIVE_LOW | \ | |
55 | GPIOHANDLE_REQUEST_BIAS_PULL_UP | \ | |
56 | GPIOHANDLE_REQUEST_BIAS_PULL_DOWN | \ | |
57 | GPIOHANDLE_REQUEST_BIAS_DISABLE | \ | |
58 | GPIOHANDLE_REQUEST_OPEN_DRAIN | \ | |
59 | GPIOHANDLE_REQUEST_OPEN_SOURCE) | |
60 | ||
61 | static int linehandle_validate_flags(u32 flags) | |
62 | { | |
63 | /* Return an error if an unknown flag is set */ | |
64 | if (flags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) | |
65 | return -EINVAL; | |
66 | ||
67 | /* | |
68 | * Do not allow both INPUT & OUTPUT flags to be set as they are | |
69 | * contradictory. | |
70 | */ | |
71 | if ((flags & GPIOHANDLE_REQUEST_INPUT) && | |
72 | (flags & GPIOHANDLE_REQUEST_OUTPUT)) | |
73 | return -EINVAL; | |
74 | ||
75 | /* | |
76 | * Do not allow OPEN_SOURCE & OPEN_DRAIN flags in a single request. If | |
77 | * the hardware actually supports enabling both at the same time the | |
78 | * electrical result would be disastrous. | |
79 | */ | |
80 | if ((flags & GPIOHANDLE_REQUEST_OPEN_DRAIN) && | |
81 | (flags & GPIOHANDLE_REQUEST_OPEN_SOURCE)) | |
82 | return -EINVAL; | |
83 | ||
84 | /* OPEN_DRAIN and OPEN_SOURCE flags only make sense for output mode. */ | |
85 | if (!(flags & GPIOHANDLE_REQUEST_OUTPUT) && | |
86 | ((flags & GPIOHANDLE_REQUEST_OPEN_DRAIN) || | |
87 | (flags & GPIOHANDLE_REQUEST_OPEN_SOURCE))) | |
88 | return -EINVAL; | |
89 | ||
90 | /* Bias flags only allowed for input or output mode. */ | |
91 | if (!((flags & GPIOHANDLE_REQUEST_INPUT) || | |
92 | (flags & GPIOHANDLE_REQUEST_OUTPUT)) && | |
93 | ((flags & GPIOHANDLE_REQUEST_BIAS_DISABLE) || | |
94 | (flags & GPIOHANDLE_REQUEST_BIAS_PULL_UP) || | |
95 | (flags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN))) | |
96 | return -EINVAL; | |
97 | ||
98 | /* Only one bias flag can be set. */ | |
99 | if (((flags & GPIOHANDLE_REQUEST_BIAS_DISABLE) && | |
100 | (flags & (GPIOHANDLE_REQUEST_BIAS_PULL_DOWN | | |
101 | GPIOHANDLE_REQUEST_BIAS_PULL_UP))) || | |
102 | ((flags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) && | |
103 | (flags & GPIOHANDLE_REQUEST_BIAS_PULL_UP))) | |
104 | return -EINVAL; | |
105 | ||
106 | return 0; | |
107 | } | |
108 | ||
109 | static long linehandle_set_config(struct linehandle_state *lh, | |
110 | void __user *ip) | |
111 | { | |
112 | struct gpiohandle_config gcnf; | |
113 | struct gpio_desc *desc; | |
114 | int i, ret; | |
115 | u32 lflags; | |
116 | unsigned long *flagsp; | |
117 | ||
118 | if (copy_from_user(&gcnf, ip, sizeof(gcnf))) | |
119 | return -EFAULT; | |
120 | ||
121 | lflags = gcnf.flags; | |
122 | ret = linehandle_validate_flags(lflags); | |
123 | if (ret) | |
124 | return ret; | |
125 | ||
126 | for (i = 0; i < lh->numdescs; i++) { | |
127 | desc = lh->descs[i]; | |
128 | flagsp = &desc->flags; | |
129 | ||
130 | assign_bit(FLAG_ACTIVE_LOW, flagsp, | |
131 | lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW); | |
132 | ||
133 | assign_bit(FLAG_OPEN_DRAIN, flagsp, | |
134 | lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN); | |
135 | ||
136 | assign_bit(FLAG_OPEN_SOURCE, flagsp, | |
137 | lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE); | |
138 | ||
139 | assign_bit(FLAG_PULL_UP, flagsp, | |
140 | lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP); | |
141 | ||
142 | assign_bit(FLAG_PULL_DOWN, flagsp, | |
143 | lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN); | |
144 | ||
145 | assign_bit(FLAG_BIAS_DISABLE, flagsp, | |
146 | lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE); | |
147 | ||
148 | /* | |
149 | * Lines have to be requested explicitly for input | |
150 | * or output, else the line will be treated "as is". | |
151 | */ | |
152 | if (lflags & GPIOHANDLE_REQUEST_OUTPUT) { | |
153 | int val = !!gcnf.default_values[i]; | |
154 | ||
155 | ret = gpiod_direction_output(desc, val); | |
156 | if (ret) | |
157 | return ret; | |
158 | } else if (lflags & GPIOHANDLE_REQUEST_INPUT) { | |
159 | ret = gpiod_direction_input(desc); | |
160 | if (ret) | |
161 | return ret; | |
162 | } | |
163 | ||
164 | atomic_notifier_call_chain(&desc->gdev->notifier, | |
165 | GPIOLINE_CHANGED_CONFIG, desc); | |
166 | } | |
167 | return 0; | |
168 | } | |
169 | ||
170 | static long linehandle_ioctl(struct file *filep, unsigned int cmd, | |
171 | unsigned long arg) | |
172 | { | |
173 | struct linehandle_state *lh = filep->private_data; | |
174 | void __user *ip = (void __user *)arg; | |
175 | struct gpiohandle_data ghd; | |
176 | DECLARE_BITMAP(vals, GPIOHANDLES_MAX); | |
177 | int i; | |
178 | ||
179 | if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { | |
180 | /* NOTE: It's ok to read values of output lines. */ | |
181 | int ret = gpiod_get_array_value_complex(false, | |
182 | true, | |
183 | lh->numdescs, | |
184 | lh->descs, | |
185 | NULL, | |
186 | vals); | |
187 | if (ret) | |
188 | return ret; | |
189 | ||
190 | memset(&ghd, 0, sizeof(ghd)); | |
191 | for (i = 0; i < lh->numdescs; i++) | |
192 | ghd.values[i] = test_bit(i, vals); | |
193 | ||
194 | if (copy_to_user(ip, &ghd, sizeof(ghd))) | |
195 | return -EFAULT; | |
196 | ||
197 | return 0; | |
198 | } else if (cmd == GPIOHANDLE_SET_LINE_VALUES_IOCTL) { | |
199 | /* | |
200 | * All line descriptors were created at once with the same | |
201 | * flags so just check if the first one is really output. | |
202 | */ | |
203 | if (!test_bit(FLAG_IS_OUT, &lh->descs[0]->flags)) | |
204 | return -EPERM; | |
205 | ||
206 | if (copy_from_user(&ghd, ip, sizeof(ghd))) | |
207 | return -EFAULT; | |
208 | ||
209 | /* Clamp all values to [0,1] */ | |
210 | for (i = 0; i < lh->numdescs; i++) | |
211 | __assign_bit(i, vals, ghd.values[i]); | |
212 | ||
213 | /* Reuse the array setting function */ | |
214 | return gpiod_set_array_value_complex(false, | |
215 | true, | |
216 | lh->numdescs, | |
217 | lh->descs, | |
218 | NULL, | |
219 | vals); | |
220 | } else if (cmd == GPIOHANDLE_SET_CONFIG_IOCTL) { | |
221 | return linehandle_set_config(lh, ip); | |
222 | } | |
223 | return -EINVAL; | |
224 | } | |
225 | ||
226 | #ifdef CONFIG_COMPAT | |
227 | static long linehandle_ioctl_compat(struct file *filep, unsigned int cmd, | |
228 | unsigned long arg) | |
229 | { | |
230 | return linehandle_ioctl(filep, cmd, (unsigned long)compat_ptr(arg)); | |
231 | } | |
232 | #endif | |
233 | ||
234 | static int linehandle_release(struct inode *inode, struct file *filep) | |
235 | { | |
236 | struct linehandle_state *lh = filep->private_data; | |
237 | struct gpio_device *gdev = lh->gdev; | |
238 | int i; | |
239 | ||
240 | for (i = 0; i < lh->numdescs; i++) | |
241 | gpiod_free(lh->descs[i]); | |
242 | kfree(lh->label); | |
243 | kfree(lh); | |
244 | put_device(&gdev->dev); | |
245 | return 0; | |
246 | } | |
247 | ||
248 | static const struct file_operations linehandle_fileops = { | |
249 | .release = linehandle_release, | |
250 | .owner = THIS_MODULE, | |
251 | .llseek = noop_llseek, | |
252 | .unlocked_ioctl = linehandle_ioctl, | |
253 | #ifdef CONFIG_COMPAT | |
254 | .compat_ioctl = linehandle_ioctl_compat, | |
255 | #endif | |
256 | }; | |
257 | ||
258 | static int linehandle_create(struct gpio_device *gdev, void __user *ip) | |
259 | { | |
260 | struct gpiohandle_request handlereq; | |
261 | struct linehandle_state *lh; | |
262 | struct file *file; | |
263 | int fd, i, count = 0, ret; | |
264 | u32 lflags; | |
265 | ||
266 | if (copy_from_user(&handlereq, ip, sizeof(handlereq))) | |
267 | return -EFAULT; | |
268 | if ((handlereq.lines == 0) || (handlereq.lines > GPIOHANDLES_MAX)) | |
269 | return -EINVAL; | |
270 | ||
271 | lflags = handlereq.flags; | |
272 | ||
273 | ret = linehandle_validate_flags(lflags); | |
274 | if (ret) | |
275 | return ret; | |
276 | ||
277 | lh = kzalloc(sizeof(*lh), GFP_KERNEL); | |
278 | if (!lh) | |
279 | return -ENOMEM; | |
280 | lh->gdev = gdev; | |
281 | get_device(&gdev->dev); | |
282 | ||
283 | /* Make sure this is terminated */ | |
284 | handlereq.consumer_label[sizeof(handlereq.consumer_label)-1] = '\0'; | |
285 | if (strlen(handlereq.consumer_label)) { | |
286 | lh->label = kstrdup(handlereq.consumer_label, | |
287 | GFP_KERNEL); | |
288 | if (!lh->label) { | |
289 | ret = -ENOMEM; | |
290 | goto out_free_lh; | |
291 | } | |
292 | } | |
293 | ||
294 | /* Request each GPIO */ | |
295 | for (i = 0; i < handlereq.lines; i++) { | |
296 | u32 offset = handlereq.lineoffsets[i]; | |
297 | struct gpio_desc *desc = gpiochip_get_desc(gdev->chip, offset); | |
298 | ||
299 | if (IS_ERR(desc)) { | |
300 | ret = PTR_ERR(desc); | |
301 | goto out_free_descs; | |
302 | } | |
303 | ||
304 | ret = gpiod_request(desc, lh->label); | |
305 | if (ret) | |
306 | goto out_free_descs; | |
307 | lh->descs[i] = desc; | |
308 | count = i + 1; | |
309 | ||
310 | if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW) | |
311 | set_bit(FLAG_ACTIVE_LOW, &desc->flags); | |
312 | if (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) | |
313 | set_bit(FLAG_OPEN_DRAIN, &desc->flags); | |
314 | if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE) | |
315 | set_bit(FLAG_OPEN_SOURCE, &desc->flags); | |
316 | if (lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE) | |
317 | set_bit(FLAG_BIAS_DISABLE, &desc->flags); | |
318 | if (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) | |
319 | set_bit(FLAG_PULL_DOWN, &desc->flags); | |
320 | if (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP) | |
321 | set_bit(FLAG_PULL_UP, &desc->flags); | |
322 | ||
323 | ret = gpiod_set_transitory(desc, false); | |
324 | if (ret < 0) | |
325 | goto out_free_descs; | |
326 | ||
327 | /* | |
328 | * Lines have to be requested explicitly for input | |
329 | * or output, else the line will be treated "as is". | |
330 | */ | |
331 | if (lflags & GPIOHANDLE_REQUEST_OUTPUT) { | |
332 | int val = !!handlereq.default_values[i]; | |
333 | ||
334 | ret = gpiod_direction_output(desc, val); | |
335 | if (ret) | |
336 | goto out_free_descs; | |
337 | } else if (lflags & GPIOHANDLE_REQUEST_INPUT) { | |
338 | ret = gpiod_direction_input(desc); | |
339 | if (ret) | |
340 | goto out_free_descs; | |
341 | } | |
342 | ||
343 | atomic_notifier_call_chain(&desc->gdev->notifier, | |
344 | GPIOLINE_CHANGED_REQUESTED, desc); | |
345 | ||
346 | dev_dbg(&gdev->dev, "registered chardev handle for line %d\n", | |
347 | offset); | |
348 | } | |
349 | /* Let i point at the last handle */ | |
350 | i--; | |
351 | lh->numdescs = handlereq.lines; | |
352 | ||
353 | fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC); | |
354 | if (fd < 0) { | |
355 | ret = fd; | |
356 | goto out_free_descs; | |
357 | } | |
358 | ||
359 | file = anon_inode_getfile("gpio-linehandle", | |
360 | &linehandle_fileops, | |
361 | lh, | |
362 | O_RDONLY | O_CLOEXEC); | |
363 | if (IS_ERR(file)) { | |
364 | ret = PTR_ERR(file); | |
365 | goto out_put_unused_fd; | |
366 | } | |
367 | ||
368 | handlereq.fd = fd; | |
369 | if (copy_to_user(ip, &handlereq, sizeof(handlereq))) { | |
370 | /* | |
371 | * fput() will trigger the release() callback, so do not go onto | |
372 | * the regular error cleanup path here. | |
373 | */ | |
374 | fput(file); | |
375 | put_unused_fd(fd); | |
376 | return -EFAULT; | |
377 | } | |
378 | ||
379 | fd_install(fd, file); | |
380 | ||
381 | dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n", | |
382 | lh->numdescs); | |
383 | ||
384 | return 0; | |
385 | ||
386 | out_put_unused_fd: | |
387 | put_unused_fd(fd); | |
388 | out_free_descs: | |
389 | for (i = 0; i < count; i++) | |
390 | gpiod_free(lh->descs[i]); | |
391 | kfree(lh->label); | |
392 | out_free_lh: | |
393 | kfree(lh); | |
394 | put_device(&gdev->dev); | |
395 | return ret; | |
396 | } | |
397 | ||
398 | /* | |
399 | * GPIO line event management | |
400 | */ | |
401 | ||
402 | /** | |
403 | * struct lineevent_state - contains the state of a userspace event | |
404 | * @gdev: the GPIO device the event pertains to | |
405 | * @label: consumer label used to tag descriptors | |
406 | * @desc: the GPIO descriptor held by this event | |
407 | * @eflags: the event flags this line was requested with | |
408 | * @irq: the interrupt that trigger in response to events on this GPIO | |
409 | * @wait: wait queue that handles blocking reads of events | |
410 | * @events: KFIFO for the GPIO events | |
411 | * @timestamp: cache for the timestamp storing it between hardirq | |
412 | * and IRQ thread, used to bring the timestamp close to the actual | |
413 | * event | |
414 | */ | |
415 | struct lineevent_state { | |
416 | struct gpio_device *gdev; | |
417 | const char *label; | |
418 | struct gpio_desc *desc; | |
419 | u32 eflags; | |
420 | int irq; | |
421 | wait_queue_head_t wait; | |
422 | DECLARE_KFIFO(events, struct gpioevent_data, 16); | |
423 | u64 timestamp; | |
424 | }; | |
425 | ||
426 | #define GPIOEVENT_REQUEST_VALID_FLAGS \ | |
427 | (GPIOEVENT_REQUEST_RISING_EDGE | \ | |
428 | GPIOEVENT_REQUEST_FALLING_EDGE) | |
429 | ||
430 | static __poll_t lineevent_poll(struct file *filep, | |
431 | struct poll_table_struct *wait) | |
432 | { | |
433 | struct lineevent_state *le = filep->private_data; | |
434 | __poll_t events = 0; | |
435 | ||
436 | poll_wait(filep, &le->wait, wait); | |
437 | ||
438 | if (!kfifo_is_empty_spinlocked_noirqsave(&le->events, &le->wait.lock)) | |
439 | events = EPOLLIN | EPOLLRDNORM; | |
440 | ||
441 | return events; | |
442 | } | |
443 | ||
444 | ||
445 | static ssize_t lineevent_read(struct file *filep, | |
446 | char __user *buf, | |
447 | size_t count, | |
448 | loff_t *f_ps) | |
449 | { | |
450 | struct lineevent_state *le = filep->private_data; | |
451 | struct gpioevent_data ge; | |
452 | ssize_t bytes_read = 0; | |
453 | int ret; | |
454 | ||
455 | if (count < sizeof(ge)) | |
456 | return -EINVAL; | |
457 | ||
458 | do { | |
459 | spin_lock(&le->wait.lock); | |
460 | if (kfifo_is_empty(&le->events)) { | |
461 | if (bytes_read) { | |
462 | spin_unlock(&le->wait.lock); | |
463 | return bytes_read; | |
464 | } | |
465 | ||
466 | if (filep->f_flags & O_NONBLOCK) { | |
467 | spin_unlock(&le->wait.lock); | |
468 | return -EAGAIN; | |
469 | } | |
470 | ||
471 | ret = wait_event_interruptible_locked(le->wait, | |
472 | !kfifo_is_empty(&le->events)); | |
473 | if (ret) { | |
474 | spin_unlock(&le->wait.lock); | |
475 | return ret; | |
476 | } | |
477 | } | |
478 | ||
479 | ret = kfifo_out(&le->events, &ge, 1); | |
480 | spin_unlock(&le->wait.lock); | |
481 | if (ret != 1) { | |
482 | /* | |
483 | * This should never happen - we were holding the lock | |
484 | * from the moment we learned the fifo is no longer | |
485 | * empty until now. | |
486 | */ | |
487 | ret = -EIO; | |
488 | break; | |
489 | } | |
490 | ||
491 | if (copy_to_user(buf + bytes_read, &ge, sizeof(ge))) | |
492 | return -EFAULT; | |
493 | bytes_read += sizeof(ge); | |
494 | } while (count >= bytes_read + sizeof(ge)); | |
495 | ||
496 | return bytes_read; | |
497 | } | |
498 | ||
499 | static int lineevent_release(struct inode *inode, struct file *filep) | |
500 | { | |
501 | struct lineevent_state *le = filep->private_data; | |
502 | struct gpio_device *gdev = le->gdev; | |
503 | ||
504 | free_irq(le->irq, le); | |
505 | gpiod_free(le->desc); | |
506 | kfree(le->label); | |
507 | kfree(le); | |
508 | put_device(&gdev->dev); | |
509 | return 0; | |
510 | } | |
511 | ||
512 | static long lineevent_ioctl(struct file *filep, unsigned int cmd, | |
513 | unsigned long arg) | |
514 | { | |
515 | struct lineevent_state *le = filep->private_data; | |
516 | void __user *ip = (void __user *)arg; | |
517 | struct gpiohandle_data ghd; | |
518 | ||
519 | /* | |
520 | * We can get the value for an event line but not set it, | |
521 | * because it is input by definition. | |
522 | */ | |
523 | if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { | |
524 | int val; | |
525 | ||
526 | memset(&ghd, 0, sizeof(ghd)); | |
527 | ||
528 | val = gpiod_get_value_cansleep(le->desc); | |
529 | if (val < 0) | |
530 | return val; | |
531 | ghd.values[0] = val; | |
532 | ||
533 | if (copy_to_user(ip, &ghd, sizeof(ghd))) | |
534 | return -EFAULT; | |
535 | ||
536 | return 0; | |
537 | } | |
538 | return -EINVAL; | |
539 | } | |
540 | ||
541 | #ifdef CONFIG_COMPAT | |
542 | static long lineevent_ioctl_compat(struct file *filep, unsigned int cmd, | |
543 | unsigned long arg) | |
544 | { | |
545 | return lineevent_ioctl(filep, cmd, (unsigned long)compat_ptr(arg)); | |
546 | } | |
547 | #endif | |
548 | ||
549 | static const struct file_operations lineevent_fileops = { | |
550 | .release = lineevent_release, | |
551 | .read = lineevent_read, | |
552 | .poll = lineevent_poll, | |
553 | .owner = THIS_MODULE, | |
554 | .llseek = noop_llseek, | |
555 | .unlocked_ioctl = lineevent_ioctl, | |
556 | #ifdef CONFIG_COMPAT | |
557 | .compat_ioctl = lineevent_ioctl_compat, | |
558 | #endif | |
559 | }; | |
560 | ||
561 | static irqreturn_t lineevent_irq_thread(int irq, void *p) | |
562 | { | |
563 | struct lineevent_state *le = p; | |
564 | struct gpioevent_data ge; | |
565 | int ret; | |
566 | ||
567 | /* Do not leak kernel stack to userspace */ | |
568 | memset(&ge, 0, sizeof(ge)); | |
569 | ||
570 | /* | |
571 | * We may be running from a nested threaded interrupt in which case | |
572 | * we didn't get the timestamp from lineevent_irq_handler(). | |
573 | */ | |
574 | if (!le->timestamp) | |
575 | ge.timestamp = ktime_get_ns(); | |
576 | else | |
577 | ge.timestamp = le->timestamp; | |
578 | ||
579 | if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE | |
580 | && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) { | |
581 | int level = gpiod_get_value_cansleep(le->desc); | |
582 | ||
583 | if (level) | |
584 | /* Emit low-to-high event */ | |
585 | ge.id = GPIOEVENT_EVENT_RISING_EDGE; | |
586 | else | |
587 | /* Emit high-to-low event */ | |
588 | ge.id = GPIOEVENT_EVENT_FALLING_EDGE; | |
589 | } else if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE) { | |
590 | /* Emit low-to-high event */ | |
591 | ge.id = GPIOEVENT_EVENT_RISING_EDGE; | |
592 | } else if (le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) { | |
593 | /* Emit high-to-low event */ | |
594 | ge.id = GPIOEVENT_EVENT_FALLING_EDGE; | |
595 | } else { | |
596 | return IRQ_NONE; | |
597 | } | |
598 | ||
599 | ret = kfifo_in_spinlocked_noirqsave(&le->events, &ge, | |
600 | 1, &le->wait.lock); | |
601 | if (ret) | |
602 | wake_up_poll(&le->wait, EPOLLIN); | |
603 | else | |
604 | pr_debug_ratelimited("event FIFO is full - event dropped\n"); | |
605 | ||
606 | return IRQ_HANDLED; | |
607 | } | |
608 | ||
609 | static irqreturn_t lineevent_irq_handler(int irq, void *p) | |
610 | { | |
611 | struct lineevent_state *le = p; | |
612 | ||
613 | /* | |
614 | * Just store the timestamp in hardirq context so we get it as | |
615 | * close in time as possible to the actual event. | |
616 | */ | |
617 | le->timestamp = ktime_get_ns(); | |
618 | ||
619 | return IRQ_WAKE_THREAD; | |
620 | } | |
621 | ||
622 | static int lineevent_create(struct gpio_device *gdev, void __user *ip) | |
623 | { | |
624 | struct gpioevent_request eventreq; | |
625 | struct lineevent_state *le; | |
626 | struct gpio_desc *desc; | |
627 | struct file *file; | |
628 | u32 offset; | |
629 | u32 lflags; | |
630 | u32 eflags; | |
631 | int fd; | |
632 | int ret; | |
633 | int irqflags = 0; | |
634 | ||
635 | if (copy_from_user(&eventreq, ip, sizeof(eventreq))) | |
636 | return -EFAULT; | |
637 | ||
638 | offset = eventreq.lineoffset; | |
639 | lflags = eventreq.handleflags; | |
640 | eflags = eventreq.eventflags; | |
641 | ||
642 | desc = gpiochip_get_desc(gdev->chip, offset); | |
643 | if (IS_ERR(desc)) | |
644 | return PTR_ERR(desc); | |
645 | ||
646 | /* Return an error if a unknown flag is set */ | |
647 | if ((lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) || | |
648 | (eflags & ~GPIOEVENT_REQUEST_VALID_FLAGS)) | |
649 | return -EINVAL; | |
650 | ||
651 | /* This is just wrong: we don't look for events on output lines */ | |
652 | if ((lflags & GPIOHANDLE_REQUEST_OUTPUT) || | |
653 | (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) || | |
654 | (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)) | |
655 | return -EINVAL; | |
656 | ||
657 | /* Only one bias flag can be set. */ | |
658 | if (((lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE) && | |
659 | (lflags & (GPIOHANDLE_REQUEST_BIAS_PULL_DOWN | | |
660 | GPIOHANDLE_REQUEST_BIAS_PULL_UP))) || | |
661 | ((lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) && | |
662 | (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP))) | |
663 | return -EINVAL; | |
664 | ||
665 | le = kzalloc(sizeof(*le), GFP_KERNEL); | |
666 | if (!le) | |
667 | return -ENOMEM; | |
668 | le->gdev = gdev; | |
669 | get_device(&gdev->dev); | |
670 | ||
671 | /* Make sure this is terminated */ | |
672 | eventreq.consumer_label[sizeof(eventreq.consumer_label)-1] = '\0'; | |
673 | if (strlen(eventreq.consumer_label)) { | |
674 | le->label = kstrdup(eventreq.consumer_label, | |
675 | GFP_KERNEL); | |
676 | if (!le->label) { | |
677 | ret = -ENOMEM; | |
678 | goto out_free_le; | |
679 | } | |
680 | } | |
681 | ||
682 | ret = gpiod_request(desc, le->label); | |
683 | if (ret) | |
684 | goto out_free_label; | |
685 | le->desc = desc; | |
686 | le->eflags = eflags; | |
687 | ||
688 | if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW) | |
689 | set_bit(FLAG_ACTIVE_LOW, &desc->flags); | |
690 | if (lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE) | |
691 | set_bit(FLAG_BIAS_DISABLE, &desc->flags); | |
692 | if (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) | |
693 | set_bit(FLAG_PULL_DOWN, &desc->flags); | |
694 | if (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP) | |
695 | set_bit(FLAG_PULL_UP, &desc->flags); | |
696 | ||
697 | ret = gpiod_direction_input(desc); | |
698 | if (ret) | |
699 | goto out_free_desc; | |
700 | ||
701 | atomic_notifier_call_chain(&desc->gdev->notifier, | |
702 | GPIOLINE_CHANGED_REQUESTED, desc); | |
703 | ||
704 | le->irq = gpiod_to_irq(desc); | |
705 | if (le->irq <= 0) { | |
706 | ret = -ENODEV; | |
707 | goto out_free_desc; | |
708 | } | |
709 | ||
710 | if (eflags & GPIOEVENT_REQUEST_RISING_EDGE) | |
711 | irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? | |
712 | IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING; | |
713 | if (eflags & GPIOEVENT_REQUEST_FALLING_EDGE) | |
714 | irqflags |= test_bit(FLAG_ACTIVE_LOW, &desc->flags) ? | |
715 | IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; | |
716 | irqflags |= IRQF_ONESHOT; | |
717 | ||
718 | INIT_KFIFO(le->events); | |
719 | init_waitqueue_head(&le->wait); | |
720 | ||
721 | /* Request a thread to read the events */ | |
722 | ret = request_threaded_irq(le->irq, | |
723 | lineevent_irq_handler, | |
724 | lineevent_irq_thread, | |
725 | irqflags, | |
726 | le->label, | |
727 | le); | |
728 | if (ret) | |
729 | goto out_free_desc; | |
730 | ||
731 | fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC); | |
732 | if (fd < 0) { | |
733 | ret = fd; | |
734 | goto out_free_irq; | |
735 | } | |
736 | ||
737 | file = anon_inode_getfile("gpio-event", | |
738 | &lineevent_fileops, | |
739 | le, | |
740 | O_RDONLY | O_CLOEXEC); | |
741 | if (IS_ERR(file)) { | |
742 | ret = PTR_ERR(file); | |
743 | goto out_put_unused_fd; | |
744 | } | |
745 | ||
746 | eventreq.fd = fd; | |
747 | if (copy_to_user(ip, &eventreq, sizeof(eventreq))) { | |
748 | /* | |
749 | * fput() will trigger the release() callback, so do not go onto | |
750 | * the regular error cleanup path here. | |
751 | */ | |
752 | fput(file); | |
753 | put_unused_fd(fd); | |
754 | return -EFAULT; | |
755 | } | |
756 | ||
757 | fd_install(fd, file); | |
758 | ||
759 | return 0; | |
760 | ||
761 | out_put_unused_fd: | |
762 | put_unused_fd(fd); | |
763 | out_free_irq: | |
764 | free_irq(le->irq, le); | |
765 | out_free_desc: | |
766 | gpiod_free(le->desc); | |
767 | out_free_label: | |
768 | kfree(le->label); | |
769 | out_free_le: | |
770 | kfree(le); | |
771 | put_device(&gdev->dev); | |
772 | return ret; | |
773 | } | |
774 | ||
775 | static void gpio_desc_to_lineinfo(struct gpio_desc *desc, | |
776 | struct gpioline_info *info) | |
777 | { | |
778 | struct gpio_chip *gc = desc->gdev->chip; | |
779 | bool ok_for_pinctrl; | |
780 | unsigned long flags; | |
781 | ||
782 | /* | |
783 | * This function takes a mutex so we must check this before taking | |
784 | * the spinlock. | |
785 | * | |
786 | * FIXME: find a non-racy way to retrieve this information. Maybe a | |
787 | * lock common to both frameworks? | |
788 | */ | |
789 | ok_for_pinctrl = | |
790 | pinctrl_gpio_can_use_line(gc->base + info->line_offset); | |
791 | ||
792 | spin_lock_irqsave(&gpio_lock, flags); | |
793 | ||
794 | if (desc->name) { | |
795 | strncpy(info->name, desc->name, sizeof(info->name)); | |
796 | info->name[sizeof(info->name) - 1] = '\0'; | |
797 | } else { | |
798 | info->name[0] = '\0'; | |
799 | } | |
800 | ||
801 | if (desc->label) { | |
802 | strncpy(info->consumer, desc->label, sizeof(info->consumer)); | |
803 | info->consumer[sizeof(info->consumer) - 1] = '\0'; | |
804 | } else { | |
805 | info->consumer[0] = '\0'; | |
806 | } | |
807 | ||
808 | /* | |
809 | * Userspace only need to know that the kernel is using this GPIO so | |
810 | * it can't use it. | |
811 | */ | |
812 | info->flags = 0; | |
813 | if (test_bit(FLAG_REQUESTED, &desc->flags) || | |
814 | test_bit(FLAG_IS_HOGGED, &desc->flags) || | |
815 | test_bit(FLAG_USED_AS_IRQ, &desc->flags) || | |
816 | test_bit(FLAG_EXPORT, &desc->flags) || | |
817 | test_bit(FLAG_SYSFS, &desc->flags) || | |
818 | !ok_for_pinctrl) | |
819 | info->flags |= GPIOLINE_FLAG_KERNEL; | |
820 | if (test_bit(FLAG_IS_OUT, &desc->flags)) | |
821 | info->flags |= GPIOLINE_FLAG_IS_OUT; | |
822 | if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) | |
823 | info->flags |= GPIOLINE_FLAG_ACTIVE_LOW; | |
824 | if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) | |
825 | info->flags |= (GPIOLINE_FLAG_OPEN_DRAIN | | |
826 | GPIOLINE_FLAG_IS_OUT); | |
827 | if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) | |
828 | info->flags |= (GPIOLINE_FLAG_OPEN_SOURCE | | |
829 | GPIOLINE_FLAG_IS_OUT); | |
830 | if (test_bit(FLAG_BIAS_DISABLE, &desc->flags)) | |
831 | info->flags |= GPIOLINE_FLAG_BIAS_DISABLE; | |
832 | if (test_bit(FLAG_PULL_DOWN, &desc->flags)) | |
833 | info->flags |= GPIOLINE_FLAG_BIAS_PULL_DOWN; | |
834 | if (test_bit(FLAG_PULL_UP, &desc->flags)) | |
835 | info->flags |= GPIOLINE_FLAG_BIAS_PULL_UP; | |
836 | ||
837 | spin_unlock_irqrestore(&gpio_lock, flags); | |
838 | } | |
839 | ||
840 | struct gpio_chardev_data { | |
841 | struct gpio_device *gdev; | |
842 | wait_queue_head_t wait; | |
843 | DECLARE_KFIFO(events, struct gpioline_info_changed, 32); | |
844 | struct notifier_block lineinfo_changed_nb; | |
845 | unsigned long *watched_lines; | |
846 | }; | |
847 | ||
848 | /* | |
849 | * gpio_ioctl() - ioctl handler for the GPIO chardev | |
850 | */ | |
851 | static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |
852 | { | |
853 | struct gpio_chardev_data *priv = filp->private_data; | |
854 | struct gpio_device *gdev = priv->gdev; | |
855 | struct gpio_chip *gc = gdev->chip; | |
856 | void __user *ip = (void __user *)arg; | |
857 | struct gpio_desc *desc; | |
858 | __u32 offset; | |
859 | int hwgpio; | |
860 | ||
861 | /* We fail any subsequent ioctl():s when the chip is gone */ | |
862 | if (!gc) | |
863 | return -ENODEV; | |
864 | ||
865 | /* Fill in the struct and pass to userspace */ | |
866 | if (cmd == GPIO_GET_CHIPINFO_IOCTL) { | |
867 | struct gpiochip_info chipinfo; | |
868 | ||
869 | memset(&chipinfo, 0, sizeof(chipinfo)); | |
870 | ||
871 | strncpy(chipinfo.name, dev_name(&gdev->dev), | |
872 | sizeof(chipinfo.name)); | |
873 | chipinfo.name[sizeof(chipinfo.name)-1] = '\0'; | |
874 | strncpy(chipinfo.label, gdev->label, | |
875 | sizeof(chipinfo.label)); | |
876 | chipinfo.label[sizeof(chipinfo.label)-1] = '\0'; | |
877 | chipinfo.lines = gdev->ngpio; | |
878 | if (copy_to_user(ip, &chipinfo, sizeof(chipinfo))) | |
879 | return -EFAULT; | |
880 | return 0; | |
881 | } else if (cmd == GPIO_GET_LINEINFO_IOCTL) { | |
882 | struct gpioline_info lineinfo; | |
883 | ||
884 | if (copy_from_user(&lineinfo, ip, sizeof(lineinfo))) | |
885 | return -EFAULT; | |
886 | ||
887 | desc = gpiochip_get_desc(gc, lineinfo.line_offset); | |
888 | if (IS_ERR(desc)) | |
889 | return PTR_ERR(desc); | |
890 | ||
891 | hwgpio = gpio_chip_hwgpio(desc); | |
892 | ||
893 | gpio_desc_to_lineinfo(desc, &lineinfo); | |
894 | ||
895 | if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) | |
896 | return -EFAULT; | |
897 | return 0; | |
898 | } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) { | |
899 | return linehandle_create(gdev, ip); | |
900 | } else if (cmd == GPIO_GET_LINEEVENT_IOCTL) { | |
901 | return lineevent_create(gdev, ip); | |
902 | } else if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) { | |
903 | struct gpioline_info lineinfo; | |
904 | ||
905 | if (copy_from_user(&lineinfo, ip, sizeof(lineinfo))) | |
906 | return -EFAULT; | |
907 | ||
908 | desc = gpiochip_get_desc(gc, lineinfo.line_offset); | |
909 | if (IS_ERR(desc)) | |
910 | return PTR_ERR(desc); | |
911 | ||
912 | hwgpio = gpio_chip_hwgpio(desc); | |
913 | ||
914 | if (test_bit(hwgpio, priv->watched_lines)) | |
915 | return -EBUSY; | |
916 | ||
917 | gpio_desc_to_lineinfo(desc, &lineinfo); | |
918 | ||
919 | if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) | |
920 | return -EFAULT; | |
921 | ||
922 | set_bit(hwgpio, priv->watched_lines); | |
923 | return 0; | |
924 | } else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) { | |
925 | if (copy_from_user(&offset, ip, sizeof(offset))) | |
926 | return -EFAULT; | |
927 | ||
928 | desc = gpiochip_get_desc(gc, offset); | |
929 | if (IS_ERR(desc)) | |
930 | return PTR_ERR(desc); | |
931 | ||
932 | hwgpio = gpio_chip_hwgpio(desc); | |
933 | ||
934 | if (!test_bit(hwgpio, priv->watched_lines)) | |
935 | return -EBUSY; | |
936 | ||
937 | clear_bit(hwgpio, priv->watched_lines); | |
938 | return 0; | |
939 | } | |
940 | return -EINVAL; | |
941 | } | |
942 | ||
943 | #ifdef CONFIG_COMPAT | |
944 | static long gpio_ioctl_compat(struct file *filp, unsigned int cmd, | |
945 | unsigned long arg) | |
946 | { | |
947 | return gpio_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); | |
948 | } | |
949 | #endif | |
950 | ||
951 | static struct gpio_chardev_data * | |
952 | to_gpio_chardev_data(struct notifier_block *nb) | |
953 | { | |
954 | return container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb); | |
955 | } | |
956 | ||
957 | static int lineinfo_changed_notify(struct notifier_block *nb, | |
958 | unsigned long action, void *data) | |
959 | { | |
960 | struct gpio_chardev_data *priv = to_gpio_chardev_data(nb); | |
961 | struct gpioline_info_changed chg; | |
962 | struct gpio_desc *desc = data; | |
963 | int ret; | |
964 | ||
965 | if (!test_bit(gpio_chip_hwgpio(desc), priv->watched_lines)) | |
966 | return NOTIFY_DONE; | |
967 | ||
968 | memset(&chg, 0, sizeof(chg)); | |
969 | chg.info.line_offset = gpio_chip_hwgpio(desc); | |
970 | chg.event_type = action; | |
971 | chg.timestamp = ktime_get_ns(); | |
972 | gpio_desc_to_lineinfo(desc, &chg.info); | |
973 | ||
974 | ret = kfifo_in_spinlocked(&priv->events, &chg, 1, &priv->wait.lock); | |
975 | if (ret) | |
976 | wake_up_poll(&priv->wait, EPOLLIN); | |
977 | else | |
978 | pr_debug_ratelimited("lineinfo event FIFO is full - event dropped\n"); | |
979 | ||
980 | return NOTIFY_OK; | |
981 | } | |
982 | ||
983 | static __poll_t lineinfo_watch_poll(struct file *filep, | |
984 | struct poll_table_struct *pollt) | |
985 | { | |
986 | struct gpio_chardev_data *priv = filep->private_data; | |
987 | __poll_t events = 0; | |
988 | ||
989 | poll_wait(filep, &priv->wait, pollt); | |
990 | ||
991 | if (!kfifo_is_empty_spinlocked_noirqsave(&priv->events, | |
992 | &priv->wait.lock)) | |
993 | events = EPOLLIN | EPOLLRDNORM; | |
994 | ||
995 | return events; | |
996 | } | |
997 | ||
998 | static ssize_t lineinfo_watch_read(struct file *filep, char __user *buf, | |
999 | size_t count, loff_t *off) | |
1000 | { | |
1001 | struct gpio_chardev_data *priv = filep->private_data; | |
1002 | struct gpioline_info_changed event; | |
1003 | ssize_t bytes_read = 0; | |
1004 | int ret; | |
1005 | ||
1006 | if (count < sizeof(event)) | |
1007 | return -EINVAL; | |
1008 | ||
1009 | do { | |
1010 | spin_lock(&priv->wait.lock); | |
1011 | if (kfifo_is_empty(&priv->events)) { | |
1012 | if (bytes_read) { | |
1013 | spin_unlock(&priv->wait.lock); | |
1014 | return bytes_read; | |
1015 | } | |
1016 | ||
1017 | if (filep->f_flags & O_NONBLOCK) { | |
1018 | spin_unlock(&priv->wait.lock); | |
1019 | return -EAGAIN; | |
1020 | } | |
1021 | ||
1022 | ret = wait_event_interruptible_locked(priv->wait, | |
1023 | !kfifo_is_empty(&priv->events)); | |
1024 | if (ret) { | |
1025 | spin_unlock(&priv->wait.lock); | |
1026 | return ret; | |
1027 | } | |
1028 | } | |
1029 | ||
1030 | ret = kfifo_out(&priv->events, &event, 1); | |
1031 | spin_unlock(&priv->wait.lock); | |
1032 | if (ret != 1) { | |
1033 | ret = -EIO; | |
1034 | break; | |
1035 | /* We should never get here. See lineevent_read(). */ | |
1036 | } | |
1037 | ||
1038 | if (copy_to_user(buf + bytes_read, &event, sizeof(event))) | |
1039 | return -EFAULT; | |
1040 | bytes_read += sizeof(event); | |
1041 | } while (count >= bytes_read + sizeof(event)); | |
1042 | ||
1043 | return bytes_read; | |
1044 | } | |
1045 | ||
1046 | /** | |
1047 | * gpio_chrdev_open() - open the chardev for ioctl operations | |
1048 | * @inode: inode for this chardev | |
1049 | * @filp: file struct for storing private data | |
1050 | * Returns 0 on success | |
1051 | */ | |
1052 | static int gpio_chrdev_open(struct inode *inode, struct file *filp) | |
1053 | { | |
1054 | struct gpio_device *gdev = container_of(inode->i_cdev, | |
1055 | struct gpio_device, chrdev); | |
1056 | struct gpio_chardev_data *priv; | |
1057 | int ret = -ENOMEM; | |
1058 | ||
1059 | /* Fail on open if the backing gpiochip is gone */ | |
1060 | if (!gdev->chip) | |
1061 | return -ENODEV; | |
1062 | ||
1063 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | |
1064 | if (!priv) | |
1065 | return -ENOMEM; | |
1066 | ||
1067 | priv->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL); | |
1068 | if (!priv->watched_lines) | |
1069 | goto out_free_priv; | |
1070 | ||
1071 | init_waitqueue_head(&priv->wait); | |
1072 | INIT_KFIFO(priv->events); | |
1073 | priv->gdev = gdev; | |
1074 | ||
1075 | priv->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify; | |
1076 | ret = atomic_notifier_chain_register(&gdev->notifier, | |
1077 | &priv->lineinfo_changed_nb); | |
1078 | if (ret) | |
1079 | goto out_free_bitmap; | |
1080 | ||
1081 | get_device(&gdev->dev); | |
1082 | filp->private_data = priv; | |
1083 | ||
1084 | ret = nonseekable_open(inode, filp); | |
1085 | if (ret) | |
1086 | goto out_unregister_notifier; | |
1087 | ||
1088 | return ret; | |
1089 | ||
1090 | out_unregister_notifier: | |
1091 | atomic_notifier_chain_unregister(&gdev->notifier, | |
1092 | &priv->lineinfo_changed_nb); | |
1093 | out_free_bitmap: | |
1094 | bitmap_free(priv->watched_lines); | |
1095 | out_free_priv: | |
1096 | kfree(priv); | |
1097 | return ret; | |
1098 | } | |
1099 | ||
1100 | /** | |
1101 | * gpio_chrdev_release() - close chardev after ioctl operations | |
1102 | * @inode: inode for this chardev | |
1103 | * @filp: file struct for storing private data | |
1104 | * Returns 0 on success | |
1105 | */ | |
1106 | static int gpio_chrdev_release(struct inode *inode, struct file *filp) | |
1107 | { | |
1108 | struct gpio_chardev_data *priv = filp->private_data; | |
1109 | struct gpio_device *gdev = priv->gdev; | |
1110 | ||
1111 | bitmap_free(priv->watched_lines); | |
1112 | atomic_notifier_chain_unregister(&gdev->notifier, | |
1113 | &priv->lineinfo_changed_nb); | |
1114 | put_device(&gdev->dev); | |
1115 | kfree(priv); | |
1116 | ||
1117 | return 0; | |
1118 | } | |
1119 | ||
1120 | static const struct file_operations gpio_fileops = { | |
1121 | .release = gpio_chrdev_release, | |
1122 | .open = gpio_chrdev_open, | |
1123 | .poll = lineinfo_watch_poll, | |
1124 | .read = lineinfo_watch_read, | |
1125 | .owner = THIS_MODULE, | |
1126 | .llseek = no_llseek, | |
1127 | .unlocked_ioctl = gpio_ioctl, | |
1128 | #ifdef CONFIG_COMPAT | |
1129 | .compat_ioctl = gpio_ioctl_compat, | |
1130 | #endif | |
1131 | }; | |
1132 | ||
1133 | int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt) | |
1134 | { | |
1135 | int ret; | |
1136 | ||
1137 | cdev_init(&gdev->chrdev, &gpio_fileops); | |
1138 | gdev->chrdev.owner = THIS_MODULE; | |
1139 | gdev->dev.devt = MKDEV(MAJOR(devt), gdev->id); | |
1140 | ||
1141 | ret = cdev_device_add(&gdev->chrdev, &gdev->dev); | |
1142 | if (ret) | |
1143 | return ret; | |
1144 | ||
1145 | chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n", | |
1146 | MAJOR(devt), gdev->id); | |
1147 | ||
1148 | return 0; | |
1149 | } | |
1150 | ||
1151 | void gpiolib_cdev_unregister(struct gpio_device *gdev) | |
1152 | { | |
1153 | cdev_device_del(&gdev->chrdev, &gdev->dev); | |
1154 | } |