Merge tag 'v3.10.76' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / tty / serial / 8250 / 8250_dw.c
index 196c26b038579f8123148137840e8f407b1761a9..9f3666c233b328951fbffc3d72105cce94627025 100644 (file)
@@ -98,7 +98,10 @@ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
                        dw8250_force_idle(p);
                        writeb(value, p->membase + (UART_LCR << p->regshift));
                }
-               dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+               /*
+                * FIXME: this deadlocks if port->lock is already held
+                * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+                */
        }
 }
 
@@ -116,8 +119,23 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
        if (offset == UART_LCR)
                d->last_lcr = value;
 
-       offset <<= p->regshift;
-       writel(value, p->membase + offset);
+       writel(value, p->membase + (offset << p->regshift));
+
+       /* Make sure LCR write wasn't ignored */
+       if (offset == UART_LCR) {
+               int tries = 1000;
+               while (tries--) {
+                       unsigned int lcr = p->serial_in(p, UART_LCR);
+                       if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
+                               return;
+                       dw8250_force_idle(p);
+                       writel(value, p->membase + (UART_LCR << p->regshift));
+               }
+               /*
+                * FIXME: this deadlocks if port->lock is already held
+                * dev_err(p->dev, "Couldn't set LCR to %d\n", value);
+                */
+       }
 }
 
 static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)