aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/input.c')
-rw-r--r--drivers/input/input.c66
1 files changed, 49 insertions, 17 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 16ec33f27c5d..cc763c96fada 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -17,6 +17,7 @@
17#include <linux/random.h> 17#include <linux/random.h>
18#include <linux/major.h> 18#include <linux/major.h>
19#include <linux/proc_fs.h> 19#include <linux/proc_fs.h>
20#include <linux/sched.h>
20#include <linux/seq_file.h> 21#include <linux/seq_file.h>
21#include <linux/poll.h> 22#include <linux/poll.h>
22#include <linux/device.h> 23#include <linux/device.h>
@@ -781,10 +782,29 @@ static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait)
781 return 0; 782 return 0;
782} 783}
783 784
785union input_seq_state {
786 struct {
787 unsigned short pos;
788 bool mutex_acquired;
789 };
790 void *p;
791};
792
784static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos) 793static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
785{ 794{
786 if (mutex_lock_interruptible(&input_mutex)) 795 union input_seq_state *state = (union input_seq_state *)&seq->private;
787 return NULL; 796 int error;
797
798 /* We need to fit into seq->private pointer */
799 BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private));
800
801 error = mutex_lock_interruptible(&input_mutex);
802 if (error) {
803 state->mutex_acquired = false;
804 return ERR_PTR(error);
805 }
806
807 state->mutex_acquired = true;
788 808
789 return seq_list_start(&input_dev_list, *pos); 809 return seq_list_start(&input_dev_list, *pos);
790} 810}
@@ -794,9 +814,12 @@ static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos)
794 return seq_list_next(v, &input_dev_list, pos); 814 return seq_list_next(v, &input_dev_list, pos);
795} 815}
796 816
797static void input_devices_seq_stop(struct seq_file *seq, void *v) 817static void input_seq_stop(struct seq_file *seq, void *v)
798{ 818{
799 mutex_unlock(&input_mutex); 819 union input_seq_state *state = (union input_seq_state *)&seq->private;
820
821 if (state->mutex_acquired)
822 mutex_unlock(&input_mutex);
800} 823}
801 824
802static void input_seq_print_bitmap(struct seq_file *seq, const char *name, 825static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
@@ -860,7 +883,7 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
860static const struct seq_operations input_devices_seq_ops = { 883static const struct seq_operations input_devices_seq_ops = {
861 .start = input_devices_seq_start, 884 .start = input_devices_seq_start,
862 .next = input_devices_seq_next, 885 .next = input_devices_seq_next,
863 .stop = input_devices_seq_stop, 886 .stop = input_seq_stop,
864 .show = input_devices_seq_show, 887 .show = input_devices_seq_show,
865}; 888};
866 889
@@ -880,40 +903,49 @@ static const struct file_operations input_devices_fileops = {
880 903
881static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) 904static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
882{ 905{
883 if (mutex_lock_interruptible(&input_mutex)) 906 union input_seq_state *state = (union input_seq_state *)&seq->private;
884 return NULL; 907 int error;
908
909 /* We need to fit into seq->private pointer */
910 BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private));
911
912 error = mutex_lock_interruptible(&input_mutex);
913 if (error) {
914 state->mutex_acquired = false;
915 return ERR_PTR(error);
916 }
917
918 state->mutex_acquired = true;
919 state->pos = *pos;
885 920
886 seq->private = (void *)(unsigned long)*pos;
887 return seq_list_start(&input_handler_list, *pos); 921 return seq_list_start(&input_handler_list, *pos);
888} 922}
889 923
890static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos) 924static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos)
891{ 925{
892 seq->private = (void *)(unsigned long)(*pos + 1); 926 union input_seq_state *state = (union input_seq_state *)&seq->private;
893 return seq_list_next(v, &input_handler_list, pos);
894}
895 927
896static void input_handlers_seq_stop(struct seq_file *seq, void *v) 928 state->pos = *pos + 1;
897{ 929 return seq_list_next(v, &input_handler_list, pos);
898 mutex_unlock(&input_mutex);
899} 930}
900 931
901static int input_handlers_seq_show(struct seq_file *seq, void *v) 932static int input_handlers_seq_show(struct seq_file *seq, void *v)
902{ 933{
903 struct input_handler *handler = container_of(v, struct input_handler, node); 934 struct input_handler *handler = container_of(v, struct input_handler, node);
935 union input_seq_state *state = (union input_seq_state *)&seq->private;
904 936
905 seq_printf(seq, "N: Number=%ld Name=%s", 937 seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name);
906 (unsigned long)seq->private, handler->name);
907 if (handler->fops) 938 if (handler->fops)
908 seq_printf(seq, " Minor=%d", handler->minor); 939 seq_printf(seq, " Minor=%d", handler->minor);
909 seq_putc(seq, '\n'); 940 seq_putc(seq, '\n');
910 941
911 return 0; 942 return 0;
912} 943}
944
913static const struct seq_operations input_handlers_seq_ops = { 945static const struct seq_operations input_handlers_seq_ops = {
914 .start = input_handlers_seq_start, 946 .start = input_handlers_seq_start,
915 .next = input_handlers_seq_next, 947 .next = input_handlers_seq_next,
916 .stop = input_handlers_seq_stop, 948 .stop = input_seq_stop,
917 .show = input_handlers_seq_show, 949 .show = input_handlers_seq_show,
918}; 950};
919 951