@@ -55,18 +55,15 @@ struct userio_device {
5555static int userio_device_write (struct serio * id , unsigned char val )
5656{
5757 struct userio_device * userio = id -> port_data ;
58- unsigned long flags ;
5958
60- spin_lock_irqsave (& userio -> buf_lock , flags );
59+ scoped_guard (spinlock_irqsave , & userio -> buf_lock ) {
60+ userio -> buf [userio -> head ] = val ;
61+ userio -> head = (userio -> head + 1 ) % USERIO_BUFSIZE ;
6162
62- userio -> buf [userio -> head ] = val ;
63- userio -> head = (userio -> head + 1 ) % USERIO_BUFSIZE ;
64-
65- if (userio -> head == userio -> tail )
66- dev_warn (userio_misc .this_device ,
67- "Buffer overflowed, userio client isn't keeping up" );
68-
69- spin_unlock_irqrestore (& userio -> buf_lock , flags );
63+ if (userio -> head == userio -> tail )
64+ dev_warn (userio_misc .this_device ,
65+ "Buffer overflowed, userio client isn't keeping up" );
66+ }
7067
7168 wake_up_interruptible (& userio -> waitq );
7269
@@ -75,9 +72,8 @@ static int userio_device_write(struct serio *id, unsigned char val)
7572
7673static int userio_char_open (struct inode * inode , struct file * file )
7774{
78- struct userio_device * userio ;
79-
80- userio = kzalloc (sizeof (* userio ), GFP_KERNEL );
75+ struct userio_device * userio __free (kfree ) =
76+ kzalloc (sizeof (* userio ), GFP_KERNEL );
8177 if (!userio )
8278 return - ENOMEM ;
8379
@@ -86,15 +82,13 @@ static int userio_char_open(struct inode *inode, struct file *file)
8682 init_waitqueue_head (& userio -> waitq );
8783
8884 userio -> serio = kzalloc (sizeof (* userio -> serio ), GFP_KERNEL );
89- if (!userio -> serio ) {
90- kfree (userio );
85+ if (!userio -> serio )
9186 return - ENOMEM ;
92- }
9387
9488 userio -> serio -> write = userio_device_write ;
95- userio -> serio -> port_data = userio ;
89+ userio -> serio -> port_data = userio ;;
9690
97- file -> private_data = userio ;
91+ file -> private_data = no_free_ptr ( userio ) ;
9892
9993 return 0 ;
10094}
@@ -118,14 +112,32 @@ static int userio_char_release(struct inode *inode, struct file *file)
118112 return 0 ;
119113}
120114
115+ static size_t userio_fetch_data (struct userio_device * userio , u8 * buf ,
116+ size_t count , size_t * copylen )
117+ {
118+ size_t available , len ;
119+
120+ guard (spinlock_irqsave )(& userio -> buf_lock );
121+
122+ available = CIRC_CNT_TO_END (userio -> head , userio -> tail ,
123+ USERIO_BUFSIZE );
124+ len = min (available , count );
125+ if (len ) {
126+ memcpy (buf , & userio -> buf [userio -> tail ], len );
127+ userio -> tail = (userio -> tail + len ) % USERIO_BUFSIZE ;
128+ }
129+
130+ * copylen = len ;
131+ return available ;
132+ }
133+
121134static ssize_t userio_char_read (struct file * file , char __user * user_buffer ,
122135 size_t count , loff_t * ppos )
123136{
124137 struct userio_device * userio = file -> private_data ;
125138 int error ;
126- size_t nonwrap_len , copylen ;
127- unsigned char buf [USERIO_BUFSIZE ];
128- unsigned long flags ;
139+ size_t available , copylen ;
140+ u8 buf [USERIO_BUFSIZE ];
129141
130142 /*
131143 * By the time we get here, the data that was waiting might have
@@ -135,21 +147,8 @@ static ssize_t userio_char_read(struct file *file, char __user *user_buffer,
135147 * of course).
136148 */
137149 for (;;) {
138- spin_lock_irqsave (& userio -> buf_lock , flags );
139-
140- nonwrap_len = CIRC_CNT_TO_END (userio -> head ,
141- userio -> tail ,
142- USERIO_BUFSIZE );
143- copylen = min (nonwrap_len , count );
144- if (copylen ) {
145- memcpy (buf , & userio -> buf [userio -> tail ], copylen );
146- userio -> tail = (userio -> tail + copylen ) %
147- USERIO_BUFSIZE ;
148- }
149-
150- spin_unlock_irqrestore (& userio -> buf_lock , flags );
151-
152- if (nonwrap_len )
150+ available = userio_fetch_data (userio , buf , count , & copylen );
151+ if (available )
153152 break ;
154153
155154 /* buffer was/is empty */
@@ -176,40 +175,21 @@ static ssize_t userio_char_read(struct file *file, char __user *user_buffer,
176175 return copylen ;
177176}
178177
179- static ssize_t userio_char_write (struct file * file , const char __user * buffer ,
180- size_t count , loff_t * ppos )
178+ static int userio_execute_cmd (struct userio_device * userio ,
179+ const struct userio_cmd * cmd )
181180{
182- struct userio_device * userio = file -> private_data ;
183- struct userio_cmd cmd ;
184- int error ;
185-
186- if (count != sizeof (cmd )) {
187- dev_warn (userio_misc .this_device , "Invalid payload size\n" );
188- return - EINVAL ;
189- }
190-
191- if (copy_from_user (& cmd , buffer , sizeof (cmd )))
192- return - EFAULT ;
193-
194- error = mutex_lock_interruptible (& userio -> mutex );
195- if (error )
196- return error ;
197-
198- switch (cmd .type ) {
181+ switch (cmd -> type ) {
199182 case USERIO_CMD_REGISTER :
200183 if (!userio -> serio -> id .type ) {
201184 dev_warn (userio_misc .this_device ,
202185 "No port type given on /dev/userio\n" );
203-
204- error = - EINVAL ;
205- goto out ;
186+ return - EINVAL ;
206187 }
207188
208189 if (userio -> running ) {
209190 dev_warn (userio_misc .this_device ,
210191 "Begin command sent, but we're already running\n" );
211- error = - EBUSY ;
212- goto out ;
192+ return - EBUSY ;
213193 }
214194
215195 userio -> running = true;
@@ -220,32 +200,51 @@ static ssize_t userio_char_write(struct file *file, const char __user *buffer,
220200 if (userio -> running ) {
221201 dev_warn (userio_misc .this_device ,
222202 "Can't change port type on an already running userio instance\n" );
223- error = - EBUSY ;
224- goto out ;
203+ return - EBUSY ;
225204 }
226205
227- userio -> serio -> id .type = cmd . data ;
206+ userio -> serio -> id .type = cmd -> data ;
228207 break ;
229208
230209 case USERIO_CMD_SEND_INTERRUPT :
231210 if (!userio -> running ) {
232211 dev_warn (userio_misc .this_device ,
233212 "The device must be registered before sending interrupts\n" );
234- error = - ENODEV ;
235- goto out ;
213+ return - ENODEV ;
236214 }
237215
238- serio_interrupt (userio -> serio , cmd . data , 0 );
216+ serio_interrupt (userio -> serio , cmd -> data , 0 );
239217 break ;
240218
241219 default :
242- error = - EOPNOTSUPP ;
243- goto out ;
220+ return - EOPNOTSUPP ;
221+ }
222+
223+ return 0 ;
224+ }
225+
226+ static ssize_t userio_char_write (struct file * file , const char __user * buffer ,
227+ size_t count , loff_t * ppos )
228+ {
229+ struct userio_device * userio = file -> private_data ;
230+ struct userio_cmd cmd ;
231+ int error ;
232+
233+ if (count != sizeof (cmd )) {
234+ dev_warn (userio_misc .this_device , "Invalid payload size\n" );
235+ return - EINVAL ;
236+ }
237+
238+ if (copy_from_user (& cmd , buffer , sizeof (cmd )))
239+ return - EFAULT ;
240+
241+ scoped_cond_guard (mutex_intr , return - EINTR , & userio -> mutex ) {
242+ error = userio_execute_cmd (userio , & cmd );
243+ if (error )
244+ return error ;
244245 }
245246
246- out :
247- mutex_unlock (& userio -> mutex );
248- return error ?: count ;
247+ return count ;
249248}
250249
251250static __poll_t userio_char_poll (struct file * file , poll_table * wait )
0 commit comments