30
30
31
31
#include <linux/debugfs.h>
32
32
#include <linux/seq_file.h>
33
+ #include <linux/kfifo.h>
33
34
#include <linux/sched/signal.h>
34
35
#include <linux/export.h>
35
36
#include <linux/slab.h>
@@ -661,17 +662,12 @@ EXPORT_SYMBOL_GPL(hid_dump_device);
661
662
/* enqueue string to 'events' ring buffer */
662
663
void hid_debug_event (struct hid_device * hdev , char * buf )
663
664
{
664
- unsigned i ;
665
665
struct hid_debug_list * list ;
666
666
unsigned long flags ;
667
667
668
668
spin_lock_irqsave (& hdev -> debug_list_lock , flags );
669
- list_for_each_entry (list , & hdev -> debug_list , node ) {
670
- for (i = 0 ; buf [i ]; i ++ )
671
- list -> hid_debug_buf [(list -> tail + i ) % HID_DEBUG_BUFSIZE ] =
672
- buf [i ];
673
- list -> tail = (list -> tail + i ) % HID_DEBUG_BUFSIZE ;
674
- }
669
+ list_for_each_entry (list , & hdev -> debug_list , node )
670
+ kfifo_in (& list -> hid_debug_fifo , buf , strlen (buf ));
675
671
spin_unlock_irqrestore (& hdev -> debug_list_lock , flags );
676
672
677
673
wake_up_interruptible (& hdev -> debug_wait );
@@ -722,8 +718,7 @@ void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 valu
722
718
hid_debug_event (hdev , buf );
723
719
724
720
kfree (buf );
725
- wake_up_interruptible (& hdev -> debug_wait );
726
-
721
+ wake_up_interruptible (& hdev -> debug_wait );
727
722
}
728
723
EXPORT_SYMBOL_GPL (hid_dump_input );
729
724
@@ -1083,8 +1078,8 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
1083
1078
goto out ;
1084
1079
}
1085
1080
1086
- if (!( list -> hid_debug_buf = kzalloc ( HID_DEBUG_BUFSIZE , GFP_KERNEL ))) {
1087
- err = - ENOMEM ;
1081
+ err = kfifo_alloc ( & list -> hid_debug_fifo , HID_DEBUG_FIFOSIZE , GFP_KERNEL );
1082
+ if ( err ) {
1088
1083
kfree (list );
1089
1084
goto out ;
1090
1085
}
@@ -1104,77 +1099,57 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
1104
1099
size_t count , loff_t * ppos )
1105
1100
{
1106
1101
struct hid_debug_list * list = file -> private_data ;
1107
- int ret = 0 , len ;
1102
+ int ret = 0 , copied ;
1108
1103
DECLARE_WAITQUEUE (wait , current );
1109
1104
1110
1105
mutex_lock (& list -> read_mutex );
1111
- while (ret == 0 ) {
1112
- if (list -> head == list -> tail ) {
1113
- add_wait_queue (& list -> hdev -> debug_wait , & wait );
1114
- set_current_state (TASK_INTERRUPTIBLE );
1115
-
1116
- while (list -> head == list -> tail ) {
1117
- if (file -> f_flags & O_NONBLOCK ) {
1118
- ret = - EAGAIN ;
1119
- break ;
1120
- }
1121
- if (signal_pending (current )) {
1122
- ret = - ERESTARTSYS ;
1123
- break ;
1124
- }
1106
+ if (kfifo_is_empty (& list -> hid_debug_fifo )) {
1107
+ add_wait_queue (& list -> hdev -> debug_wait , & wait );
1108
+ set_current_state (TASK_INTERRUPTIBLE );
1109
+
1110
+ while (kfifo_is_empty (& list -> hid_debug_fifo )) {
1111
+ if (file -> f_flags & O_NONBLOCK ) {
1112
+ ret = - EAGAIN ;
1113
+ break ;
1114
+ }
1125
1115
1126
- if (!list -> hdev || !list -> hdev -> debug ) {
1127
- ret = - EIO ;
1128
- set_current_state (TASK_RUNNING );
1129
- goto out ;
1130
- }
1116
+ if (signal_pending (current )) {
1117
+ ret = - ERESTARTSYS ;
1118
+ break ;
1119
+ }
1131
1120
1132
- /* allow O_NONBLOCK from other threads */
1133
- mutex_unlock (& list -> read_mutex );
1134
- schedule ();
1135
- mutex_lock (& list -> read_mutex );
1136
- set_current_state (TASK_INTERRUPTIBLE );
1121
+ /* if list->hdev is NULL we cannot remove_wait_queue().
1122
+ * if list->hdev->debug is 0 then hid_debug_unregister()
1123
+ * was already called and list->hdev is being destroyed.
1124
+ * if we add remove_wait_queue() here we can hit a race.
1125
+ */
1126
+ if (!list -> hdev || !list -> hdev -> debug ) {
1127
+ ret = - EIO ;
1128
+ set_current_state (TASK_RUNNING );
1129
+ goto out ;
1137
1130
}
1138
1131
1139
- set_current_state (TASK_RUNNING );
1140
- remove_wait_queue (& list -> hdev -> debug_wait , & wait );
1132
+ /* allow O_NONBLOCK from other threads */
1133
+ mutex_unlock (& list -> read_mutex );
1134
+ schedule ();
1135
+ mutex_lock (& list -> read_mutex );
1136
+ set_current_state (TASK_INTERRUPTIBLE );
1141
1137
}
1142
1138
1143
- if ( ret )
1144
- goto out ;
1139
+ __set_current_state ( TASK_RUNNING );
1140
+ remove_wait_queue ( & list -> hdev -> debug_wait , & wait ) ;
1145
1141
1146
- /* pass the ringbuffer contents to userspace */
1147
- copy_rest :
1148
- if (list -> tail == list -> head )
1142
+ if (ret )
1149
1143
goto out ;
1150
- if (list -> tail > list -> head ) {
1151
- len = list -> tail - list -> head ;
1152
- if (len > count )
1153
- len = count ;
1154
-
1155
- if (copy_to_user (buffer + ret , & list -> hid_debug_buf [list -> head ], len )) {
1156
- ret = - EFAULT ;
1157
- goto out ;
1158
- }
1159
- ret += len ;
1160
- list -> head += len ;
1161
- } else {
1162
- len = HID_DEBUG_BUFSIZE - list -> head ;
1163
- if (len > count )
1164
- len = count ;
1165
-
1166
- if (copy_to_user (buffer , & list -> hid_debug_buf [list -> head ], len )) {
1167
- ret = - EFAULT ;
1168
- goto out ;
1169
- }
1170
- list -> head = 0 ;
1171
- ret += len ;
1172
- count -= len ;
1173
- if (count > 0 )
1174
- goto copy_rest ;
1175
- }
1176
-
1177
1144
}
1145
+
1146
+ /* pass the fifo content to userspace, locking is not needed with only
1147
+ * one concurrent reader and one concurrent writer
1148
+ */
1149
+ ret = kfifo_to_user (& list -> hid_debug_fifo , buffer , count , & copied );
1150
+ if (ret )
1151
+ goto out ;
1152
+ ret = copied ;
1178
1153
out :
1179
1154
mutex_unlock (& list -> read_mutex );
1180
1155
return ret ;
@@ -1185,7 +1160,7 @@ static __poll_t hid_debug_events_poll(struct file *file, poll_table *wait)
1185
1160
struct hid_debug_list * list = file -> private_data ;
1186
1161
1187
1162
poll_wait (file , & list -> hdev -> debug_wait , wait );
1188
- if (list -> head != list -> tail )
1163
+ if (! kfifo_is_empty ( & list -> hid_debug_fifo ) )
1189
1164
return EPOLLIN | EPOLLRDNORM ;
1190
1165
if (!list -> hdev -> debug )
1191
1166
return EPOLLERR | EPOLLHUP ;
@@ -1200,7 +1175,7 @@ static int hid_debug_events_release(struct inode *inode, struct file *file)
1200
1175
spin_lock_irqsave (& list -> hdev -> debug_list_lock , flags );
1201
1176
list_del (& list -> node );
1202
1177
spin_unlock_irqrestore (& list -> hdev -> debug_list_lock , flags );
1203
- kfree ( list -> hid_debug_buf );
1178
+ kfifo_free ( & list -> hid_debug_fifo );
1204
1179
kfree (list );
1205
1180
1206
1181
return 0 ;
@@ -1246,4 +1221,3 @@ void hid_debug_exit(void)
1246
1221
{
1247
1222
debugfs_remove_recursive (hid_debug_root );
1248
1223
}
1249
-
0 commit comments