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: i8042 - use guard notation when acquiring spinlock

Using guard notation makes the code more compact and error handling
more robust by ensuring that locks are released in all code paths
when control leaves critical section.

Link: https://lore.kernel.org/r/20240905041732.2034348-14-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

+87 -127
+87 -127
drivers/input/serio/i8042.c
··· 197 197 int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, 198 198 struct serio *serio)) 199 199 { 200 - unsigned long flags; 201 - int ret = 0; 200 + guard(spinlock_irqsave)(&i8042_lock); 202 201 203 - spin_lock_irqsave(&i8042_lock, flags); 204 - 205 - if (i8042_platform_filter) { 206 - ret = -EBUSY; 207 - goto out; 208 - } 202 + if (i8042_platform_filter) 203 + return -EBUSY; 209 204 210 205 i8042_platform_filter = filter; 211 - 212 - out: 213 - spin_unlock_irqrestore(&i8042_lock, flags); 214 - return ret; 206 + return 0; 215 207 } 216 208 EXPORT_SYMBOL(i8042_install_filter); 217 209 218 210 int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, 219 211 struct serio *port)) 220 212 { 221 - unsigned long flags; 222 - int ret = 0; 213 + guard(spinlock_irqsave)(&i8042_lock); 223 214 224 - spin_lock_irqsave(&i8042_lock, flags); 225 - 226 - if (i8042_platform_filter != filter) { 227 - ret = -EINVAL; 228 - goto out; 229 - } 215 + if (i8042_platform_filter != filter) 216 + return -EINVAL; 230 217 231 218 i8042_platform_filter = NULL; 232 - 233 - out: 234 - spin_unlock_irqrestore(&i8042_lock, flags); 235 - return ret; 219 + return 0; 236 220 } 237 221 EXPORT_SYMBOL(i8042_remove_filter); 238 222 ··· 255 271 256 272 static int i8042_flush(void) 257 273 { 258 - unsigned long flags; 259 274 unsigned char data, str; 260 275 int count = 0; 261 - int retval = 0; 262 276 263 - spin_lock_irqsave(&i8042_lock, flags); 277 + guard(spinlock_irqsave)(&i8042_lock); 264 278 265 279 while ((str = i8042_read_status()) & I8042_STR_OBF) { 266 - if (count++ < I8042_BUFFER_SIZE) { 267 - udelay(50); 268 - data = i8042_read_data(); 269 - dbg("%02x <- i8042 (flush, %s)\n", 270 - data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); 271 - } else { 272 - retval = -EIO; 273 - break; 274 - } 280 + if (count++ >= I8042_BUFFER_SIZE) 281 + return -EIO; 282 + 283 + udelay(50); 284 + data = i8042_read_data(); 285 + dbg("%02x <- i8042 (flush, %s)\n", 286 + data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); 275 287 } 276 288 277 - spin_unlock_irqrestore(&i8042_lock, flags); 278 - 279 - return retval; 289 + return 0; 280 290 } 281 291 282 292 /* ··· 327 349 328 350 int i8042_command(unsigned char *param, int command) 329 351 { 330 - unsigned long flags; 331 - int retval; 332 - 333 352 if (!i8042_present) 334 353 return -1; 335 354 336 - spin_lock_irqsave(&i8042_lock, flags); 337 - retval = __i8042_command(param, command); 338 - spin_unlock_irqrestore(&i8042_lock, flags); 355 + guard(spinlock_irqsave)(&i8042_lock); 339 356 340 - return retval; 357 + return __i8042_command(param, command); 341 358 } 342 359 EXPORT_SYMBOL(i8042_command); 343 360 ··· 342 369 343 370 static int i8042_kbd_write(struct serio *port, unsigned char c) 344 371 { 345 - unsigned long flags; 346 - int retval = 0; 372 + int error; 347 373 348 - spin_lock_irqsave(&i8042_lock, flags); 374 + guard(spinlock_irqsave)(&i8042_lock); 349 375 350 - if (!(retval = i8042_wait_write())) { 351 - dbg("%02x -> i8042 (kbd-data)\n", c); 352 - i8042_write_data(c); 353 - } 376 + error = i8042_wait_write(); 377 + if (error) 378 + return error; 354 379 355 - spin_unlock_irqrestore(&i8042_lock, flags); 380 + dbg("%02x -> i8042 (kbd-data)\n", c); 381 + i8042_write_data(c); 356 382 357 - return retval; 383 + return 0; 358 384 } 359 385 360 386 /* ··· 432 460 device_set_wakeup_enable(&serio->dev, true); 433 461 } 434 462 435 - spin_lock_irq(&i8042_lock); 463 + guard(spinlock_irq)(&i8042_lock); 436 464 port->exists = true; 437 - spin_unlock_irq(&i8042_lock); 438 465 439 466 return 0; 440 467 } ··· 447 476 { 448 477 struct i8042_port *port = serio->port_data; 449 478 450 - spin_lock_irq(&i8042_lock); 451 - port->exists = false; 452 - port->serio = NULL; 453 - spin_unlock_irq(&i8042_lock); 479 + scoped_guard(spinlock_irq, &i8042_lock) { 480 + port->exists = false; 481 + port->serio = NULL; 482 + } 454 483 455 484 /* 456 485 * We need to make sure that interrupt handler finishes using ··· 554 583 { 555 584 struct i8042_port *port; 556 585 struct serio *serio; 557 - unsigned long flags; 558 586 unsigned char str, data; 559 587 unsigned int dfl; 560 588 unsigned int port_no; 561 589 bool filtered; 562 590 563 - spin_lock_irqsave(&i8042_lock, flags); 591 + scoped_guard(spinlock_irqsave, &i8042_lock) { 592 + str = i8042_read_status(); 593 + if (unlikely(~str & I8042_STR_OBF)) 594 + return false; 564 595 565 - str = i8042_read_status(); 566 - if (unlikely(~str & I8042_STR_OBF)) { 567 - spin_unlock_irqrestore(&i8042_lock, flags); 568 - return false; 596 + data = i8042_read_data(); 597 + 598 + if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { 599 + port_no = i8042_handle_mux(str, &data, &dfl); 600 + } else { 601 + 602 + dfl = (str & I8042_STR_PARITY) ? SERIO_PARITY : 0; 603 + if ((str & I8042_STR_TIMEOUT) && !i8042_notimeout) 604 + dfl |= SERIO_TIMEOUT; 605 + 606 + port_no = (str & I8042_STR_AUXDATA) ? 607 + I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; 608 + } 609 + 610 + port = &i8042_ports[port_no]; 611 + serio = port->exists ? port->serio : NULL; 612 + 613 + filter_dbg(port->driver_bound, 614 + data, "<- i8042 (interrupt, %d, %d%s%s)\n", 615 + port_no, irq, 616 + dfl & SERIO_PARITY ? ", bad parity" : "", 617 + dfl & SERIO_TIMEOUT ? ", timeout" : ""); 618 + 619 + filtered = i8042_filter(data, str, serio); 569 620 } 570 - 571 - data = i8042_read_data(); 572 - 573 - if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { 574 - port_no = i8042_handle_mux(str, &data, &dfl); 575 - } else { 576 - 577 - dfl = (str & I8042_STR_PARITY) ? SERIO_PARITY : 0; 578 - if ((str & I8042_STR_TIMEOUT) && !i8042_notimeout) 579 - dfl |= SERIO_TIMEOUT; 580 - 581 - port_no = (str & I8042_STR_AUXDATA) ? 582 - I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; 583 - } 584 - 585 - port = &i8042_ports[port_no]; 586 - serio = port->exists ? port->serio : NULL; 587 - 588 - filter_dbg(port->driver_bound, data, "<- i8042 (interrupt, %d, %d%s%s)\n", 589 - port_no, irq, 590 - dfl & SERIO_PARITY ? ", bad parity" : "", 591 - dfl & SERIO_TIMEOUT ? ", timeout" : ""); 592 - 593 - filtered = i8042_filter(data, str, serio); 594 - 595 - spin_unlock_irqrestore(&i8042_lock, flags); 596 621 597 622 if (likely(serio && !filtered)) 598 623 serio_interrupt(serio, data, dfl); ··· 746 779 747 780 static irqreturn_t i8042_aux_test_irq(int irq, void *dev_id) 748 781 { 749 - unsigned long flags; 750 782 unsigned char str, data; 751 - int ret = 0; 752 783 753 - spin_lock_irqsave(&i8042_lock, flags); 784 + guard(spinlock_irqsave)(&i8042_lock); 785 + 754 786 str = i8042_read_status(); 755 - if (str & I8042_STR_OBF) { 756 - data = i8042_read_data(); 757 - dbg("%02x <- i8042 (aux_test_irq, %s)\n", 758 - data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); 759 - if (i8042_irq_being_tested && 760 - data == 0xa5 && (str & I8042_STR_AUXDATA)) 761 - complete(&i8042_aux_irq_delivered); 762 - ret = 1; 763 - } 764 - spin_unlock_irqrestore(&i8042_lock, flags); 787 + if (!(str & I8042_STR_OBF)) 788 + return IRQ_NONE; 765 789 766 - return IRQ_RETVAL(ret); 790 + data = i8042_read_data(); 791 + dbg("%02x <- i8042 (aux_test_irq, %s)\n", 792 + data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); 793 + 794 + if (i8042_irq_being_tested && data == 0xa5 && (str & I8042_STR_AUXDATA)) 795 + complete(&i8042_aux_irq_delivered); 796 + 797 + return IRQ_HANDLED; 767 798 } 768 799 769 800 /* ··· 802 837 int retval = -1; 803 838 bool irq_registered = false; 804 839 bool aux_loop_broken = false; 805 - unsigned long flags; 806 840 unsigned char param; 807 841 808 842 /* ··· 885 921 if (i8042_enable_aux_port()) 886 922 goto out; 887 923 888 - spin_lock_irqsave(&i8042_lock, flags); 924 + scoped_guard(spinlock_irqsave, &i8042_lock) { 925 + init_completion(&i8042_aux_irq_delivered); 926 + i8042_irq_being_tested = true; 889 927 890 - init_completion(&i8042_aux_irq_delivered); 891 - i8042_irq_being_tested = true; 892 - 893 - param = 0xa5; 894 - retval = __i8042_command(&param, I8042_CMD_AUX_LOOP & 0xf0ff); 895 - 896 - spin_unlock_irqrestore(&i8042_lock, flags); 897 - 898 - if (retval) 899 - goto out; 928 + param = 0xa5; 929 + retval = __i8042_command(&param, I8042_CMD_AUX_LOOP & 0xf0ff); 930 + if (retval) 931 + goto out; 932 + } 900 933 901 934 if (wait_for_completion_timeout(&i8042_aux_irq_delivered, 902 935 msecs_to_jiffies(250)) == 0) { ··· 981 1020 982 1021 static int i8042_controller_init(void) 983 1022 { 984 - unsigned long flags; 985 1023 int n = 0; 986 1024 unsigned char ctr[2]; 987 1025 ··· 1017 1057 * Handle keylock. 1018 1058 */ 1019 1059 1020 - spin_lock_irqsave(&i8042_lock, flags); 1021 - if (~i8042_read_status() & I8042_STR_KEYLOCK) { 1022 - if (i8042_unlock) 1023 - i8042_ctr |= I8042_CTR_IGNKEYLOCK; 1024 - else 1025 - pr_warn("Warning: Keylock active\n"); 1060 + scoped_guard(spinlock_irqsave, &i8042_lock) { 1061 + if (~i8042_read_status() & I8042_STR_KEYLOCK) { 1062 + if (i8042_unlock) 1063 + i8042_ctr |= I8042_CTR_IGNKEYLOCK; 1064 + else 1065 + pr_warn("Warning: Keylock active\n"); 1066 + } 1026 1067 } 1027 - spin_unlock_irqrestore(&i8042_lock, flags); 1028 1068 1029 1069 /* 1030 1070 * If the chip is configured into nontranslated mode by the BIOS, don't