Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 315679 Details for
Bug 432945
i8042 mouse fails in virtualized environment (between 2.6.18-8.el5 and 2.6.18-53.1.13.el5)
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Backport of upstream changes to i8042.c --- does NOT fix the bug
linux-2.6-input-i8042-update.patch (text/plain), 8.81 KB, created by
Markus Armbruster
on 2008-09-03 19:45:03 UTC
(
hide
)
Description:
Backport of upstream changes to i8042.c --- does NOT fix the bug
Filename:
MIME Type:
Creator:
Markus Armbruster
Created:
2008-09-03 19:45:03 UTC
Size:
8.81 KB
patch
obsolete
>--- linux-2.6.18.noarch/drivers/input/serio/i8042.c 2008-08-29 14:22:32.000000000 -0400 >+++ linux-2.6.18-hacked/drivers/input/serio/i8042.c 2008-08-29 15:00:11.000000000 -0400 >@@ -106,6 +106,7 @@ static unsigned char i8042_ctr; > static unsigned char i8042_mux_present; > static unsigned char i8042_kbd_irq_registered; > static unsigned char i8042_aux_irq_registered; >+static unsigned char i8042_suppress_kbd_ack; > static struct platform_device *i8042_platform_device; > > static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs); >@@ -254,25 +255,10 @@ static int i8042_kbd_write(struct serio > static int i8042_aux_write(struct serio *serio, unsigned char c) > { > struct i8042_port *port = serio->port_data; >- int retval; >- >-/* >- * Send the byte out. >- */ >- >- if (port->mux == -1) >- retval = i8042_command(&c, I8042_CMD_AUX_SEND); >- else >- retval = i8042_command(&c, I8042_CMD_MUX_SEND + port->mux); >- >-/* >- * Make sure the interrupt happens and the character is received even >- * in the case the IRQ isn't wired, so that we can receive further >- * characters later. >- */ > >- i8042_interrupt(0, NULL, NULL); >- return retval; >+ return i8042_command(&c, port->mux == -1 ? >+ I8042_CMD_AUX_SEND : >+ I8042_CMD_MUX_SEND + port->mux); > } > > /* >@@ -299,7 +285,14 @@ static void i8042_stop(struct serio *ser > struct i8042_port *port = serio->port_data; > > port->exists = 0; >- synchronize_sched(); >+ >+ /* >+ * We synchronize with both AUX and KBD IRQs because there is >+ * a (very unlikely) chance that AUX IRQ is raised for KBD port >+ * and vice versa. >+ */ >+ synchronize_irq(I8042_AUX_IRQ); >+ synchronize_irq(I8042_KBD_IRQ); > port->serio = NULL; > } > >@@ -316,7 +309,7 @@ static irqreturn_t i8042_interrupt(int i > unsigned char str, data; > unsigned int dfl; > unsigned int port_no; >- int ret; >+ int ret = 1; > > spin_lock_irqsave(&i8042_lock, flags); > str = i8042_read_status(); >@@ -336,23 +329,27 @@ static irqreturn_t i8042_interrupt(int i > dfl = 0; > if (str & I8042_STR_MUXERR) { > dbg("MUX error, status is %02x, data is %02x", str, data); >- switch (data) { >- default: > /* > * When MUXERR condition is signalled the data register can only contain > * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately >- * it is not always the case. Some KBC just get confused which port the >- * data came from and signal error leaving the data intact. They _do not_ >- * revert to legacy mode (actually I've never seen KBC reverting to legacy >- * mode yet, when we see one we'll add proper handling). >- * Anyway, we will assume that the data came from the same serio last byte >+ * it is not always the case. Some KBCs also report 0xfc when there is >+ * nothing connected to the port while others sometimes get confused which >+ * port the data came from and signal error leaving the data intact. They >+ * _do not_ revert to legacy mode (actually I've never seen KBC reverting >+ * to legacy mode yet, when we see one we'll add proper handling). >+ * Anyway, we process 0xfc, 0xfd, 0xfe and 0xff as timeouts, and for the >+ * rest assume that the data came from the same serio last byte > * was transmitted (if transmission happened not too long ago). > */ >+ >+ switch (data) { >+ default: > if (time_before(jiffies, last_transmit + HZ/10)) { > str = last_str; > break; > } > /* fall through - report timeout */ >+ case 0xfc: > case 0xfd: > case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break; > case 0xff: dfl = SERIO_PARITY; data = 0xfe; break; >@@ -378,10 +375,16 @@ static irqreturn_t i8042_interrupt(int i > dfl & SERIO_PARITY ? ", bad parity" : "", > dfl & SERIO_TIMEOUT ? ", timeout" : ""); > >+ if (unlikely(i8042_suppress_kbd_ack)) >+ if (port_no == I8042_KBD_PORT_NO && >+ (data == 0xfa || data == 0xfe)) { >+ i8042_suppress_kbd_ack--; >+ goto out; >+ } >+ > if (likely(port->exists)) > serio_interrupt(port->serio, data, dfl, regs); > >- ret = 1; > out: > return IRQ_RETVAL(ret); > } >@@ -396,6 +399,8 @@ static int i8042_enable_kbd_port(void) > i8042_ctr |= I8042_CTR_KBDINT; > > if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { >+ i8042_ctr &= ~I8042_CTR_KBDINT; >+ i8042_ctr |= I8042_CTR_KBDDIS; > printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n"); > return -EIO; > } >@@ -413,6 +418,8 @@ static int i8042_enable_aux_port(void) > i8042_ctr |= I8042_CTR_AUXINT; > > if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { >+ i8042_ctr &= ~I8042_CTR_AUXINT; >+ i8042_ctr |= I8042_CTR_AUXDIS; > printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n"); > return -EIO; > } >@@ -523,6 +530,7 @@ static irqreturn_t __devinit i8042_aux_t > { > unsigned long flags; > unsigned char str, data; >+ int ret = 0; > > spin_lock_irqsave(&i8042_lock, flags); > str = i8042_read_status(); >@@ -531,12 +539,40 @@ static irqreturn_t __devinit i8042_aux_t > if (i8042_irq_being_tested && > data == 0xa5 && (str & I8042_STR_AUXDATA)) > complete(&i8042_aux_irq_delivered); >+ ret = 1; > } > spin_unlock_irqrestore(&i8042_lock, flags); > >- return IRQ_HANDLED; >+ return IRQ_RETVAL(ret); > } > >+/* >+ * i8042_toggle_aux - enables or disables AUX port on i8042 via command and >+ * verifies success by readinng CTR. Used when testing for presence of AUX >+ * port. >+ */ >+static int __devinit i8042_toggle_aux(int on) >+{ >+ unsigned char param; >+ int i; >+ >+ if (i8042_command(¶m, >+ on ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE)) >+ return -1; >+ >+ /* some chips need some time to set the I8042_CTR_AUXDIS bit */ >+ for (i = 0; i < 100; i++) { >+ udelay(50); >+ >+ if (i8042_command(¶m, I8042_CMD_CTL_RCTR)) >+ return -1; >+ >+ if (!(param & I8042_CTR_AUXDIS) == on) >+ return 0; >+ } >+ >+ return -1; >+} > > /* > * i8042_check_aux() applies as much paranoia as it can at detecting >@@ -547,6 +583,7 @@ static int __devinit i8042_check_aux(voi > { > int retval = -1; > int irq_registered = 0; >+ int aux_loop_broken = 0; > unsigned long flags; > unsigned char param; > >@@ -563,7 +600,8 @@ static int __devinit i8042_check_aux(voi > */ > > param = 0x5a; >- if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0x5a) { >+ retval = i8042_command(¶m, I8042_CMD_AUX_LOOP); >+ if (retval || param != 0x5a) { > > /* > * External connection test - filters out AT-soldered PS/2 i8042's >@@ -576,22 +614,25 @@ static int __devinit i8042_check_aux(voi > if (i8042_command(¶m, I8042_CMD_AUX_TEST) || > (param && param != 0xfa && param != 0xff)) > return -1; >+ >+/* >+ * If AUX_LOOP completed without error but returned unexpected data >+ * mark it as broken >+ */ >+ if (!retval) >+ aux_loop_broken = 1; > } > > /* > * Bit assignment test - filters out PS/2 i8042's in AT mode > */ > >- if (i8042_command(¶m, I8042_CMD_AUX_DISABLE)) >- return -1; >- if (i8042_command(¶m, I8042_CMD_CTL_RCTR) || (~param & I8042_CTR_AUXDIS)) { >+ if (i8042_toggle_aux(0)) { > printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); > printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); > } > >- if (i8042_command(¶m, I8042_CMD_AUX_ENABLE)) >- return -1; >- if (i8042_command(¶m, I8042_CMD_CTL_RCTR) || (param & I8042_CTR_AUXDIS)) >+ if (i8042_toggle_aux(1)) > return -1; > > /* >@@ -599,7 +640,7 @@ static int __devinit i8042_check_aux(voi > * used it for a PCI card or somethig else. > */ > >- if (i8042_noloop) { >+ if (i8042_noloop || aux_loop_broken) { > /* > * Without LOOP command we can't test AUX IRQ delivery. Assume the port > * is working and hope we are right. >@@ -770,6 +811,13 @@ static void i8042_controller_reset(void) > i8042_flush(); > > /* >+ * Disable both KBD and AUX interfaces so they don't get in the way >+ */ >+ >+ i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; >+ i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); >+ >+/* > * Disable MUX mode if present. > */ > >@@ -842,11 +890,14 @@ static long i8042_panic_blink(long count > led ^= 0x01 | 0x04; > while (i8042_read_status() & I8042_STR_IBF) > DELAY; >+ dbg("%02x -> i8042 (panic blink)", 0xed); >+ i8042_suppress_kbd_ack = 2; > i8042_write_data(0xed); /* set leds */ > DELAY; > while (i8042_read_status() & I8042_STR_IBF) > DELAY; > DELAY; >+ dbg("%02x -> i8042 (panic blink)", led); > i8042_write_data(led); > DELAY; > last_blink = count; >@@ -890,8 +941,12 @@ static int i8042_resume(struct platform_ > i8042_ctr |= I8042_CTR_AUXDIS | I8042_CTR_KBDDIS; > i8042_ctr &= ~(I8042_CTR_AUXINT | I8042_CTR_KBDINT); > if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { >- printk(KERN_ERR "i8042: Can't write CTR to resume\n"); >- return -EIO; >+ printk(KERN_WARNING "i8042: Can't write CTR to resume, retrying...\n"); >+ msleep(50); >+ if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) { >+ printk(KERN_ERR "i8042: CTR write retry failed\n"); >+ return -EIO; >+ } > } > > if (i8042_mux_present) { >@@ -1007,7 +1062,7 @@ static void __devinit i8042_register_por > } > } > >-static void __devinit i8042_unregister_ports(void) >+static void __devexit i8042_unregister_ports(void) > { > int i; >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 432945
: 315679 |
317864