Skip to content

Commit 54f9517

Browse files
committed
Input: userio - switch to using cleanup functions
Use __free() and guard() primitives to simplify the code and error handling. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 6ed8b7c commit 54f9517

File tree

1 file changed

+70
-71
lines changed

1 file changed

+70
-71
lines changed

drivers/input/serio/userio.c

Lines changed: 70 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,15 @@ struct userio_device {
5555
static 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

7673
static 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+
121134
static 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

251250
static __poll_t userio_char_poll(struct file *file, poll_table *wait)

0 commit comments

Comments
 (0)