aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r--drivers/gpio/gpiolib.c99
1 files changed, 86 insertions, 13 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index f0fc3a0d37c8..93ed0e00c578 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -21,6 +21,7 @@
21#include <linux/uaccess.h> 21#include <linux/uaccess.h>
22#include <linux/compat.h> 22#include <linux/compat.h>
23#include <linux/anon_inodes.h> 23#include <linux/anon_inodes.h>
24#include <linux/file.h>
24#include <linux/kfifo.h> 25#include <linux/kfifo.h>
25#include <linux/poll.h> 26#include <linux/poll.h>
26#include <linux/timekeeping.h> 27#include <linux/timekeeping.h>
@@ -333,6 +334,13 @@ struct linehandle_state {
333 u32 numdescs; 334 u32 numdescs;
334}; 335};
335 336
337#define GPIOHANDLE_REQUEST_VALID_FLAGS \
338 (GPIOHANDLE_REQUEST_INPUT | \
339 GPIOHANDLE_REQUEST_OUTPUT | \
340 GPIOHANDLE_REQUEST_ACTIVE_LOW | \
341 GPIOHANDLE_REQUEST_OPEN_DRAIN | \
342 GPIOHANDLE_REQUEST_OPEN_SOURCE)
343
336static long linehandle_ioctl(struct file *filep, unsigned int cmd, 344static long linehandle_ioctl(struct file *filep, unsigned int cmd,
337 unsigned long arg) 345 unsigned long arg)
338{ 346{
@@ -344,6 +352,8 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
344 if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { 352 if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
345 int val; 353 int val;
346 354
355 memset(&ghd, 0, sizeof(ghd));
356
347 /* TODO: check if descriptors are really input */ 357 /* TODO: check if descriptors are really input */
348 for (i = 0; i < lh->numdescs; i++) { 358 for (i = 0; i < lh->numdescs; i++) {
349 val = gpiod_get_value_cansleep(lh->descs[i]); 359 val = gpiod_get_value_cansleep(lh->descs[i]);
@@ -414,6 +424,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
414{ 424{
415 struct gpiohandle_request handlereq; 425 struct gpiohandle_request handlereq;
416 struct linehandle_state *lh; 426 struct linehandle_state *lh;
427 struct file *file;
417 int fd, i, ret; 428 int fd, i, ret;
418 429
419 if (copy_from_user(&handlereq, ip, sizeof(handlereq))) 430 if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
@@ -444,6 +455,17 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
444 u32 lflags = handlereq.flags; 455 u32 lflags = handlereq.flags;
445 struct gpio_desc *desc; 456 struct gpio_desc *desc;
446 457
458 if (offset >= gdev->ngpio) {
459 ret = -EINVAL;
460 goto out_free_descs;
461 }
462
463 /* Return an error if a unknown flag is set */
464 if (lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) {
465 ret = -EINVAL;
466 goto out_free_descs;
467 }
468
447 desc = &gdev->descs[offset]; 469 desc = &gdev->descs[offset];
448 ret = gpiod_request(desc, lh->label); 470 ret = gpiod_request(desc, lh->label);
449 if (ret) 471 if (ret)
@@ -479,26 +501,41 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
479 i--; 501 i--;
480 lh->numdescs = handlereq.lines; 502 lh->numdescs = handlereq.lines;
481 503
482 fd = anon_inode_getfd("gpio-linehandle", 504 fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
483 &linehandle_fileops,
484 lh,
485 O_RDONLY | O_CLOEXEC);
486 if (fd < 0) { 505 if (fd < 0) {
487 ret = fd; 506 ret = fd;
488 goto out_free_descs; 507 goto out_free_descs;
489 } 508 }
490 509
510 file = anon_inode_getfile("gpio-linehandle",
511 &linehandle_fileops,
512 lh,
513 O_RDONLY | O_CLOEXEC);
514 if (IS_ERR(file)) {
515 ret = PTR_ERR(file);
516 goto out_put_unused_fd;
517 }
518
491 handlereq.fd = fd; 519 handlereq.fd = fd;
492 if (copy_to_user(ip, &handlereq, sizeof(handlereq))) { 520 if (copy_to_user(ip, &handlereq, sizeof(handlereq))) {
493 ret = -EFAULT; 521 /*
494 goto out_free_descs; 522 * fput() will trigger the release() callback, so do not go onto
523 * the regular error cleanup path here.
524 */
525 fput(file);
526 put_unused_fd(fd);
527 return -EFAULT;
495 } 528 }
496 529
530 fd_install(fd, file);
531
497 dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n", 532 dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
498 lh->numdescs); 533 lh->numdescs);
499 534
500 return 0; 535 return 0;
501 536
537out_put_unused_fd:
538 put_unused_fd(fd);
502out_free_descs: 539out_free_descs:
503 for (; i >= 0; i--) 540 for (; i >= 0; i--)
504 gpiod_free(lh->descs[i]); 541 gpiod_free(lh->descs[i]);
@@ -536,6 +573,10 @@ struct lineevent_state {
536 struct mutex read_lock; 573 struct mutex read_lock;
537}; 574};
538 575
576#define GPIOEVENT_REQUEST_VALID_FLAGS \
577 (GPIOEVENT_REQUEST_RISING_EDGE | \
578 GPIOEVENT_REQUEST_FALLING_EDGE)
579
539static unsigned int lineevent_poll(struct file *filep, 580static unsigned int lineevent_poll(struct file *filep,
540 struct poll_table_struct *wait) 581 struct poll_table_struct *wait)
541{ 582{
@@ -623,6 +664,8 @@ static long lineevent_ioctl(struct file *filep, unsigned int cmd,
623 if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { 664 if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
624 int val; 665 int val;
625 666
667 memset(&ghd, 0, sizeof(ghd));
668
626 val = gpiod_get_value_cansleep(le->desc); 669 val = gpiod_get_value_cansleep(le->desc);
627 if (val < 0) 670 if (val < 0)
628 return val; 671 return val;
@@ -695,6 +738,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
695 struct gpioevent_request eventreq; 738 struct gpioevent_request eventreq;
696 struct lineevent_state *le; 739 struct lineevent_state *le;
697 struct gpio_desc *desc; 740 struct gpio_desc *desc;
741 struct file *file;
698 u32 offset; 742 u32 offset;
699 u32 lflags; 743 u32 lflags;
700 u32 eflags; 744 u32 eflags;
@@ -726,6 +770,18 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
726 lflags = eventreq.handleflags; 770 lflags = eventreq.handleflags;
727 eflags = eventreq.eventflags; 771 eflags = eventreq.eventflags;
728 772
773 if (offset >= gdev->ngpio) {
774 ret = -EINVAL;
775 goto out_free_label;
776 }
777
778 /* Return an error if a unknown flag is set */
779 if ((lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) ||
780 (eflags & ~GPIOEVENT_REQUEST_VALID_FLAGS)) {
781 ret = -EINVAL;
782 goto out_free_label;
783 }
784
729 /* This is just wrong: we don't look for events on output lines */ 785 /* This is just wrong: we don't look for events on output lines */
730 if (lflags & GPIOHANDLE_REQUEST_OUTPUT) { 786 if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
731 ret = -EINVAL; 787 ret = -EINVAL;
@@ -777,23 +833,38 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
777 if (ret) 833 if (ret)
778 goto out_free_desc; 834 goto out_free_desc;
779 835
780 fd = anon_inode_getfd("gpio-event", 836 fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
781 &lineevent_fileops,
782 le,
783 O_RDONLY | O_CLOEXEC);
784 if (fd < 0) { 837 if (fd < 0) {
785 ret = fd; 838 ret = fd;
786 goto out_free_irq; 839 goto out_free_irq;
787 } 840 }
788 841
842 file = anon_inode_getfile("gpio-event",
843 &lineevent_fileops,
844 le,
845 O_RDONLY | O_CLOEXEC);
846 if (IS_ERR(file)) {
847 ret = PTR_ERR(file);
848 goto out_put_unused_fd;
849 }
850
789 eventreq.fd = fd; 851 eventreq.fd = fd;
790 if (copy_to_user(ip, &eventreq, sizeof(eventreq))) { 852 if (copy_to_user(ip, &eventreq, sizeof(eventreq))) {
791 ret = -EFAULT; 853 /*
792 goto out_free_irq; 854 * fput() will trigger the release() callback, so do not go onto
855 * the regular error cleanup path here.
856 */
857 fput(file);
858 put_unused_fd(fd);
859 return -EFAULT;
793 } 860 }
794 861
862 fd_install(fd, file);
863
795 return 0; 864 return 0;
796 865
866out_put_unused_fd:
867 put_unused_fd(fd);
797out_free_irq: 868out_free_irq:
798 free_irq(le->irq, le); 869 free_irq(le->irq, le);
799out_free_desc: 870out_free_desc:
@@ -823,6 +894,8 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
823 if (cmd == GPIO_GET_CHIPINFO_IOCTL) { 894 if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
824 struct gpiochip_info chipinfo; 895 struct gpiochip_info chipinfo;
825 896
897 memset(&chipinfo, 0, sizeof(chipinfo));
898
826 strncpy(chipinfo.name, dev_name(&gdev->dev), 899 strncpy(chipinfo.name, dev_name(&gdev->dev),
827 sizeof(chipinfo.name)); 900 sizeof(chipinfo.name));
828 chipinfo.name[sizeof(chipinfo.name)-1] = '\0'; 901 chipinfo.name[sizeof(chipinfo.name)-1] = '\0';
@@ -839,7 +912,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
839 912
840 if (copy_from_user(&lineinfo, ip, sizeof(lineinfo))) 913 if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
841 return -EFAULT; 914 return -EFAULT;
842 if (lineinfo.line_offset > gdev->ngpio) 915 if (lineinfo.line_offset >= gdev->ngpio)
843 return -EINVAL; 916 return -EINVAL;
844 917
845 desc = &gdev->descs[lineinfo.line_offset]; 918 desc = &gdev->descs[lineinfo.line_offset];