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 - tease apart interrupt handler

In preparation to using guard notation when acquiring mutexes and
spinlocks factor out handling of active multiplexing mode from
i8042_interrupt().

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

+89 -62
+89 -62
drivers/input/serio/i8042.c
··· 178 178 static struct platform_device *i8042_platform_device; 179 179 static struct notifier_block i8042_kbd_bind_notifier_block; 180 180 181 - static irqreturn_t i8042_interrupt(int irq, void *dev_id); 181 + static bool i8042_handle_data(int irq); 182 182 static bool (*i8042_platform_filter)(unsigned char data, unsigned char str, 183 183 struct serio *serio); 184 184 ··· 434 434 * See if there is any data appeared while we were messing with 435 435 * port state. 436 436 */ 437 - i8042_interrupt(0, NULL); 437 + i8042_handle_data(0); 438 438 } 439 439 440 440 /* ··· 518 518 } 519 519 520 520 /* 521 - * i8042_interrupt() is the most important function in this driver - 522 - * it handles the interrupts from the i8042, and sends incoming bytes 523 - * to the upper layers. 524 - */ 525 - 526 - static irqreturn_t i8042_interrupt(int irq, void *dev_id) 527 - { 528 - struct i8042_port *port; 529 - struct serio *serio; 530 - unsigned long flags; 531 - unsigned char str, data; 532 - unsigned int dfl; 533 - unsigned int port_no; 534 - bool filtered; 535 - int ret = 1; 536 - 537 - spin_lock_irqsave(&i8042_lock, flags); 538 - 539 - str = i8042_read_status(); 540 - if (unlikely(~str & I8042_STR_OBF)) { 541 - spin_unlock_irqrestore(&i8042_lock, flags); 542 - if (irq) 543 - dbg("Interrupt %d, without any data\n", irq); 544 - ret = 0; 545 - goto out; 546 - } 547 - 548 - data = i8042_read_data(); 549 - 550 - if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { 551 - static unsigned long last_transmit; 552 - static unsigned char last_str; 553 - 554 - dfl = 0; 555 - if (str & I8042_STR_MUXERR) { 556 - dbg("MUX error, status is %02x, data is %02x\n", 557 - str, data); 558 - /* 521 + * i8042_handle_mux() handles case when data is coming from one of 522 + * the multiplexed ports. It would be simple if not for quirks with 523 + * handling errors: 524 + * 559 525 * When MUXERR condition is signalled the data register can only contain 560 526 * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately 561 527 * it is not always the case. Some KBCs also report 0xfc when there is ··· 533 567 * rest assume that the data came from the same serio last byte 534 568 * was transmitted (if transmission happened not too long ago). 535 569 */ 570 + static int i8042_handle_mux(u8 str, u8 *data, unsigned int *dfl) 571 + { 572 + static unsigned long last_transmit; 573 + static unsigned long last_port; 574 + unsigned int mux_port; 536 575 537 - switch (data) { 538 - default: 539 - if (time_before(jiffies, last_transmit + HZ/10)) { 540 - str = last_str; 541 - break; 542 - } 543 - fallthrough; /* report timeout */ 544 - case 0xfc: 545 - case 0xfd: 546 - case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break; 547 - case 0xff: dfl = SERIO_PARITY; data = 0xfe; break; 576 + mux_port = (str >> 6) & 3; 577 + *dfl = 0; 578 + 579 + if (str & I8042_STR_MUXERR) { 580 + dbg("MUX error, status is %02x, data is %02x\n", 581 + str, *data); 582 + 583 + switch (*data) { 584 + default: 585 + if (time_before(jiffies, last_transmit + HZ/10)) { 586 + mux_port = last_port; 587 + break; 548 588 } 589 + fallthrough; /* report timeout */ 590 + case 0xfc: 591 + case 0xfd: 592 + case 0xfe: 593 + *dfl = SERIO_TIMEOUT; 594 + *data = 0xfe; 595 + break; 596 + case 0xff: 597 + *dfl = SERIO_PARITY; 598 + *data = 0xfe; 599 + break; 549 600 } 601 + } 550 602 551 - port_no = I8042_MUX_PORT_NO + ((str >> 6) & 3); 552 - last_str = str; 553 - last_transmit = jiffies; 603 + last_port = mux_port; 604 + last_transmit = jiffies; 605 + 606 + return I8042_MUX_PORT_NO + mux_port; 607 + } 608 + 609 + /* 610 + * i8042_handle_data() is the most important function in this driver - 611 + * it reads the data from the i8042, determines its destination serio 612 + * port, and sends received byte to the upper layers. 613 + * 614 + * Returns true if there was data waiting, false otherwise. 615 + */ 616 + static bool i8042_handle_data(int irq) 617 + { 618 + struct i8042_port *port; 619 + struct serio *serio; 620 + unsigned long flags; 621 + unsigned char str, data; 622 + unsigned int dfl; 623 + unsigned int port_no; 624 + bool filtered; 625 + 626 + spin_lock_irqsave(&i8042_lock, flags); 627 + 628 + str = i8042_read_status(); 629 + if (unlikely(~str & I8042_STR_OBF)) { 630 + spin_unlock_irqrestore(&i8042_lock, flags); 631 + return false; 632 + } 633 + 634 + data = i8042_read_data(); 635 + 636 + if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { 637 + port_no = i8042_handle_mux(str, &data, &dfl); 554 638 } else { 555 639 556 - dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | 557 - ((str & I8042_STR_TIMEOUT && !i8042_notimeout) ? SERIO_TIMEOUT : 0); 640 + dfl = (str & I8042_STR_PARITY) ? SERIO_PARITY : 0; 641 + if ((str & I8042_STR_TIMEOUT) && !i8042_notimeout) 642 + dfl |= SERIO_TIMEOUT; 558 643 559 644 port_no = (str & I8042_STR_AUXDATA) ? 560 645 I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; ··· 626 609 if (likely(serio && !filtered)) 627 610 serio_interrupt(serio, data, dfl); 628 611 629 - out: 630 - return IRQ_RETVAL(ret); 612 + return true; 613 + } 614 + 615 + static irqreturn_t i8042_interrupt(int irq, void *dev_id) 616 + { 617 + if (unlikely(!i8042_handle_data(irq))) { 618 + dbg("Interrupt %d, without any data\n", irq); 619 + return IRQ_NONE; 620 + } 621 + 622 + return IRQ_HANDLED; 631 623 } 632 624 633 625 /* ··· 1242 1216 if (i8042_mux_present) { 1243 1217 if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports()) 1244 1218 pr_warn("failed to resume active multiplexor, mouse won't work\n"); 1245 - } else if (i8042_ports[I8042_AUX_PORT_NO].serio) 1219 + } else if (i8042_ports[I8042_AUX_PORT_NO].serio) { 1246 1220 i8042_enable_aux_port(); 1221 + } 1247 1222 1248 1223 if (i8042_ports[I8042_KBD_PORT_NO].serio) 1249 1224 i8042_enable_kbd_port(); 1250 1225 1251 - i8042_interrupt(0, NULL); 1226 + i8042_handle_data(0); 1252 1227 1253 1228 return 0; 1254 1229 } ··· 1280 1253 static int i8042_pm_resume_noirq(struct device *dev) 1281 1254 { 1282 1255 if (i8042_forcenorestore || !pm_resume_via_firmware()) 1283 - i8042_interrupt(0, NULL); 1256 + i8042_handle_data(0); 1284 1257 1285 1258 return 0; 1286 1259 } ··· 1317 1290 1318 1291 static int i8042_pm_thaw(struct device *dev) 1319 1292 { 1320 - i8042_interrupt(0, NULL); 1293 + i8042_handle_data(0); 1321 1294 1322 1295 return 0; 1323 1296 }