Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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/20240905041732.2034348-24-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

+88 -89
+88 -89
drivers/input/serio/userio.c
··· 55 55 static int userio_device_write(struct serio *id, unsigned char val) 56 56 { 57 57 struct userio_device *userio = id->port_data; 58 - unsigned long flags; 59 58 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; 61 62 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 + } 70 67 71 68 wake_up_interruptible(&userio->waitq); 72 69 ··· 72 75 73 76 static int userio_char_open(struct inode *inode, struct file *file) 74 77 { 75 - struct userio_device *userio; 76 - 77 - userio = kzalloc(sizeof(*userio), GFP_KERNEL); 78 + struct userio_device *userio __free(kfree) = 79 + kzalloc(sizeof(*userio), GFP_KERNEL); 78 80 if (!userio) 79 81 return -ENOMEM; 80 82 ··· 82 86 init_waitqueue_head(&userio->waitq); 83 87 84 88 userio->serio = kzalloc(sizeof(*userio->serio), GFP_KERNEL); 85 - if (!userio->serio) { 86 - kfree(userio); 89 + if (!userio->serio) 87 90 return -ENOMEM; 88 - } 89 91 90 92 userio->serio->write = userio_device_write; 91 - userio->serio->port_data = userio; 93 + userio->serio->port_data = userio;; 92 94 93 - file->private_data = userio; 95 + file->private_data = no_free_ptr(userio); 94 96 95 97 return 0; 96 98 } ··· 112 118 return 0; 113 119 } 114 120 121 + static size_t userio_fetch_data(struct userio_device *userio, u8 *buf, 122 + size_t count, size_t *copylen) 123 + { 124 + size_t available, len; 125 + 126 + guard(spinlock_irqsave)(&userio->buf_lock); 127 + 128 + available = CIRC_CNT_TO_END(userio->head, userio->tail, 129 + USERIO_BUFSIZE); 130 + len = min(available, count); 131 + if (len) { 132 + memcpy(buf, &userio->buf[userio->tail], len); 133 + userio->tail = (userio->tail + len) % USERIO_BUFSIZE; 134 + } 135 + 136 + *copylen = len; 137 + return available; 138 + } 139 + 115 140 static ssize_t userio_char_read(struct file *file, char __user *user_buffer, 116 141 size_t count, loff_t *ppos) 117 142 { 118 143 struct userio_device *userio = file->private_data; 119 144 int error; 120 - size_t nonwrap_len, copylen; 121 - unsigned char buf[USERIO_BUFSIZE]; 122 - unsigned long flags; 145 + size_t available, copylen; 146 + u8 buf[USERIO_BUFSIZE]; 123 147 124 148 /* 125 149 * By the time we get here, the data that was waiting might have ··· 147 135 * of course). 148 136 */ 149 137 for (;;) { 150 - spin_lock_irqsave(&userio->buf_lock, flags); 151 - 152 - nonwrap_len = CIRC_CNT_TO_END(userio->head, 153 - userio->tail, 154 - USERIO_BUFSIZE); 155 - copylen = min(nonwrap_len, count); 156 - if (copylen) { 157 - memcpy(buf, &userio->buf[userio->tail], copylen); 158 - userio->tail = (userio->tail + copylen) % 159 - USERIO_BUFSIZE; 160 - } 161 - 162 - spin_unlock_irqrestore(&userio->buf_lock, flags); 163 - 164 - if (nonwrap_len) 138 + available = userio_fetch_data(userio, buf, count, &copylen); 139 + if (available) 165 140 break; 166 141 167 142 /* buffer was/is empty */ ··· 175 176 return copylen; 176 177 } 177 178 179 + static int userio_execute_cmd(struct userio_device *userio, 180 + const struct userio_cmd *cmd) 181 + { 182 + switch (cmd->type) { 183 + case USERIO_CMD_REGISTER: 184 + if (!userio->serio->id.type) { 185 + dev_warn(userio_misc.this_device, 186 + "No port type given on /dev/userio\n"); 187 + return -EINVAL; 188 + } 189 + 190 + if (userio->running) { 191 + dev_warn(userio_misc.this_device, 192 + "Begin command sent, but we're already running\n"); 193 + return -EBUSY; 194 + } 195 + 196 + userio->running = true; 197 + serio_register_port(userio->serio); 198 + break; 199 + 200 + case USERIO_CMD_SET_PORT_TYPE: 201 + if (userio->running) { 202 + dev_warn(userio_misc.this_device, 203 + "Can't change port type on an already running userio instance\n"); 204 + return -EBUSY; 205 + } 206 + 207 + userio->serio->id.type = cmd->data; 208 + break; 209 + 210 + case USERIO_CMD_SEND_INTERRUPT: 211 + if (!userio->running) { 212 + dev_warn(userio_misc.this_device, 213 + "The device must be registered before sending interrupts\n"); 214 + return -ENODEV; 215 + } 216 + 217 + serio_interrupt(userio->serio, cmd->data, 0); 218 + break; 219 + 220 + default: 221 + return -EOPNOTSUPP; 222 + } 223 + 224 + return 0; 225 + } 226 + 178 227 static ssize_t userio_char_write(struct file *file, const char __user *buffer, 179 228 size_t count, loff_t *ppos) 180 229 { ··· 238 191 if (copy_from_user(&cmd, buffer, sizeof(cmd))) 239 192 return -EFAULT; 240 193 241 - error = mutex_lock_interruptible(&userio->mutex); 242 - if (error) 243 - return error; 244 - 245 - switch (cmd.type) { 246 - case USERIO_CMD_REGISTER: 247 - if (!userio->serio->id.type) { 248 - dev_warn(userio_misc.this_device, 249 - "No port type given on /dev/userio\n"); 250 - 251 - error = -EINVAL; 252 - goto out; 253 - } 254 - 255 - if (userio->running) { 256 - dev_warn(userio_misc.this_device, 257 - "Begin command sent, but we're already running\n"); 258 - error = -EBUSY; 259 - goto out; 260 - } 261 - 262 - userio->running = true; 263 - serio_register_port(userio->serio); 264 - break; 265 - 266 - case USERIO_CMD_SET_PORT_TYPE: 267 - if (userio->running) { 268 - dev_warn(userio_misc.this_device, 269 - "Can't change port type on an already running userio instance\n"); 270 - error = -EBUSY; 271 - goto out; 272 - } 273 - 274 - userio->serio->id.type = cmd.data; 275 - break; 276 - 277 - case USERIO_CMD_SEND_INTERRUPT: 278 - if (!userio->running) { 279 - dev_warn(userio_misc.this_device, 280 - "The device must be registered before sending interrupts\n"); 281 - error = -ENODEV; 282 - goto out; 283 - } 284 - 285 - serio_interrupt(userio->serio, cmd.data, 0); 286 - break; 287 - 288 - default: 289 - error = -EOPNOTSUPP; 290 - goto out; 194 + scoped_cond_guard(mutex_intr, return -EINTR, &userio->mutex) { 195 + error = userio_execute_cmd(userio, &cmd); 196 + if (error) 197 + return error; 291 198 } 292 199 293 - out: 294 - mutex_unlock(&userio->mutex); 295 - return error ?: count; 200 + return count; 296 201 } 297 202 298 203 static __poll_t userio_char_poll(struct file *file, poll_table *wait)