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