* [PATCH] 8250 UART backup timer
@ 2006-06-27 19:04 Alex Williamson
2006-06-27 19:15 ` H. Peter Anvin
2006-07-05 3:39 ` Alex Williamson
0 siblings, 2 replies; 6+ messages in thread
From: Alex Williamson @ 2006-06-27 19:04 UTC (permalink / raw)
To: rmk+serial; +Cc: linux-kernel
The patch below works around a minor bug found in the UART of the
remote management card used in many HP ia64 and parisc servers (aka the
Diva UARTs). The problem is that the UART does not reassert the THRE
interrupt if it has been previously cleared and the IIR THRI bit is
re-enabled. This can produce a very annoying failure mode when used as
a serial console, allowing a boot/reboot to hang indefinitely until an
RX interrupt kicks it into working again (ie. an unattended reboot could
stall).
To solve this problem, a backup timer is introduced that runs
alongside the standard interrupt driven mechanism. This timer wakes up
periodically, checks for a hang condition and gets characters moving
again. This backup mechanism is only enabled if the UART is detected as
having this problem, so systems without these UARTs will have no
additional overhead.
This version of the patch incorporates previous comments from Pavel
and removes races in the bug detection code. The test is now done
before the irq linking to prevent races with interrupt handler clearing
the THRE interrupt. Short delays and syncs are also added to ensure the
device is able to update register state before the result is tested.
Comments? Thanks,
Alex
Signed-off-by: Alex Williamson <alex.williamson@hp.com>
---
diff -r e3554576c29a drivers/serial/8250.c
--- a/drivers/serial/8250.c Sun Jun 18 02:00:07 2006 +0000
+++ b/drivers/serial/8250.c Tue Jun 27 12:27:03 2006 -0600
@@ -353,6 +353,23 @@ serial_out(struct uart_8250_port *up, in
}
}
+static void
+serial_out_sync(struct uart_8250_port *up, int offset, int value)
+{
+ switch (up->port.iotype) {
+ case UPIO_MEM:
+ case UPIO_MEM32:
+#ifdef CONFIG_SERIAL_8250_AU1X00
+ case UPIO_AU:
+#endif
+ serial_out(up, offset, value);
+ (void)serial_in(up, UART_LCR); /* safe, no side-effects */
+ break;
+ default:
+ serial_out(up, offset, value);
+ }
+}
+
/*
* We used to support using pause I/O for certain machines. We
* haven't supported this for a while, but just in case it's badly
@@ -1436,6 +1453,13 @@ static void serial_unlink_irq_chain(stru
serial_do_unlink(i, up);
}
+/* Base timer interval for polling */
+static inline int
+poll_timeout(int timeout)
+{
+ return timeout > 6 ? (timeout / 2 - 2) : 1;
+}
+
/*
* This function is used to handle ports that do not have an
* interrupt. This doesn't work very well for 16450's, but gives
@@ -1445,16 +1469,52 @@ static void serial8250_timeout(unsigned
static void serial8250_timeout(unsigned long data)
{
struct uart_8250_port *up = (struct uart_8250_port *)data;
- unsigned int timeout;
unsigned int iir;
iir = serial_in(up, UART_IIR);
if (!(iir & UART_IIR_NO_INT))
serial8250_handle_port(up, NULL);
- timeout = up->port.timeout;
- timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
- mod_timer(&up->timer, jiffies + timeout);
+ mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
+}
+
+static void serial8250_backup_timeout(unsigned long data)
+{
+ struct uart_8250_port *up = (struct uart_8250_port *)data;
+ unsigned int iir, ier = 0;
+
+ /*
+ * Must disable interrupts or else we risk racing with the interrupt
+ * based handler.
+ */
+ if (is_real_interrupt(up->port.irq)) {
+ ier = serial_in(up, UART_IER);
+ serial_out(up, UART_IER, 0);
+ }
+
+ iir = serial_in(up, UART_IIR);
+
+ /*
+ * This should be a safe test for anyone who doesn't trust the
+ * IIR bits on their UART, but it's specifically designed for
+ * the "Diva" UART used on the management processor on many HP
+ * ia64 and parisc boxes.
+ */
+ if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
+ (!uart_circ_empty(&up->port.info->xmit) || up->port.x_char) &&
+ (serial_in(up, UART_LSR) & UART_LSR_THRE)) {
+ iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
+ iir |= UART_IIR_THRI;
+ }
+
+ if (!(iir & UART_IIR_NO_INT))
+ serial8250_handle_port(up, NULL);
+
+ if (is_real_interrupt(up->port.irq))
+ serial_out(up, UART_IER, ier);
+
+ /* Standard timer interval plus 0.2s to keep the port running */
+ mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout) + HZ/5);
}
static unsigned int serial8250_tx_empty(struct uart_port *port)
@@ -1523,6 +1583,36 @@ static void serial8250_break_ctl(struct
up->lcr &= ~UART_LCR_SBC;
serial_out(up, UART_LCR, up->lcr);
spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+/*
+ * Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
+{
+ unsigned int status, timeout = 10000;
+
+ /* Wait up to 10ms for the character(s) to be sent. */
+ do {
+ status = serial_in(up, UART_LSR);
+
+ if (status & UART_LSR_BI)
+ up->lsr_break_flag = UART_LSR_BI;
+
+ if (--timeout == 0)
+ break;
+ udelay(1);
+ } while ((status & bits) != bits);
+
+ /* Wait up to 1s for flow control if necessary */
+ if (up->port.flags & UPF_CONS_FLOW) {
+ timeout = 1000000;
+ while (--timeout &&
+ ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
+ udelay(1);
+ }
}
static int serial8250_startup(struct uart_port *port)
@@ -1598,18 +1688,50 @@ static int serial8250_startup(struct uar
serial_outp(up, UART_LCR, 0);
}
+ if (is_real_interrupt(up->port.irq)) {
+ /*
+ * Test for UARTs that do not reassert THRE when the
+ * transmitter is idle and the interrupt has already
+ * been cleared. Real 16550s should always reassert
+ * this interrupt whenever the transmitter is idle and
+ * the interrupt is enabled. Delays are necessary to
+ * allow register changes to become visible.
+ */
+ spin_lock_irqsave(&up->port.lock, flags);
+
+ wait_for_xmitr(up, UART_LSR_THRE);
+ serial_out_sync(up, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow THRE to set */
+ (void)serial_in(up, UART_IIR);
+ serial_out(up, UART_IER, 0);
+ serial_out_sync(up, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow a working UART time to re-assert THRE */
+ iir = serial_in(up, UART_IIR);
+ serial_out(up, UART_IER, 0);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+ /*
+ * If the interrupt is not reasserted, setup a timer to
+ * kick the UART on a regular basis.
+ */
+ if (iir & UART_IIR_NO_INT) {
+ pr_debug("ttyS%d - using backup timer\n", port->line);
+ up->timer.function = serial8250_backup_timeout;
+ up->timer.data = (unsigned long)up;
+ mod_timer(&up->timer, jiffies +
+ poll_timeout(up->port.timeout) + HZ/5);
+ }
+ }
+
/*
* If the "interrupt" for this port doesn't correspond with any
* hardware interrupt, we use a timer-based system. The original
* driver used to do this with IRQ0.
*/
if (!is_real_interrupt(up->port.irq)) {
- unsigned int timeout = up->port.timeout;
-
- timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
-
up->timer.data = (unsigned long)up;
- mod_timer(&up->timer, jiffies + timeout);
+ mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
} else {
retval = serial_link_irq_chain(up);
if (retval)
@@ -1725,9 +1847,9 @@ static void serial8250_shutdown(struct u
*/
(void) serial_in(up, UART_RX);
- if (!is_real_interrupt(up->port.irq))
- del_timer_sync(&up->timer);
- else
+ del_timer_sync(&up->timer);
+ up->timer.function = serial8250_timeout;
+ if (is_real_interrupt(up->port.irq))
serial_unlink_irq_chain(up);
}
@@ -2187,36 +2309,6 @@ serial8250_register_ports(struct uart_dr
#ifdef CONFIG_SERIAL_8250_CONSOLE
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/*
- * Wait for transmitter & holding register to empty
- */
-static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- do {
- status = serial_in(up, UART_LSR);
-
- if (status & UART_LSR_BI)
- up->lsr_break_flag = UART_LSR_BI;
-
- if (--tmout == 0)
- break;
- udelay(1);
- } while ((status & bits) != bits);
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- tmout = 1000000;
- while (--tmout &&
- ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
- udelay(1);
- }
-}
-
static void serial8250_console_putchar(struct uart_port *port, int ch)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] 8250 UART backup timer
2006-06-27 19:04 [PATCH] 8250 UART backup timer Alex Williamson
@ 2006-06-27 19:15 ` H. Peter Anvin
2006-06-27 19:32 ` Alex Williamson
2006-09-13 20:18 ` Aristeu Sergio Rozanski Filho
2006-07-05 3:39 ` Alex Williamson
1 sibling, 2 replies; 6+ messages in thread
From: H. Peter Anvin @ 2006-06-27 19:15 UTC (permalink / raw)
To: Alex Williamson; +Cc: rmk+serial, linux-kernel
Alex Williamson wrote:
> The patch below works around a minor bug found in the UART of the
> remote management card used in many HP ia64 and parisc servers (aka the
> Diva UARTs). The problem is that the UART does not reassert the THRE
> interrupt if it has been previously cleared and the IIR THRI bit is
> re-enabled. This can produce a very annoying failure mode when used as
> a serial console, allowing a boot/reboot to hang indefinitely until an
> RX interrupt kicks it into working again (ie. an unattended reboot could
> stall).
>
> To solve this problem, a backup timer is introduced that runs
> alongside the standard interrupt driven mechanism. This timer wakes up
> periodically, checks for a hang condition and gets characters moving
> again. This backup mechanism is only enabled if the UART is detected as
> having this problem, so systems without these UARTs will have no
> additional overhead.
>
> This version of the patch incorporates previous comments from Pavel
> and removes races in the bug detection code. The test is now done
> before the irq linking to prevent races with interrupt handler clearing
> the THRE interrupt. Short delays and syncs are also added to ensure the
> device is able to update register state before the result is tested.
> Comments? Thanks,
>
I have seen this same bug in soft UART IP from "a major vendor."
-hpa
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] 8250 UART backup timer
2006-06-27 19:15 ` H. Peter Anvin
@ 2006-06-27 19:32 ` Alex Williamson
2006-09-13 20:18 ` Aristeu Sergio Rozanski Filho
1 sibling, 0 replies; 6+ messages in thread
From: Alex Williamson @ 2006-06-27 19:32 UTC (permalink / raw)
To: H. Peter Anvin; +Cc: rmk+serial, linux-kernel
On Tue, 2006-06-27 at 12:15 -0700, H. Peter Anvin wrote:
> Alex Williamson wrote:
> > The patch below works around a minor bug found in the UART of the
> > remote management card used in many HP ia64 and parisc servers (aka the
> > Diva UARTs). The problem is that the UART does not reassert the THRE
> > interrupt if it has been previously cleared and the IIR THRI bit is
> > re-enabled. This can produce a very annoying failure mode when used as
> > a serial console, allowing a boot/reboot to hang indefinitely until an
> > RX interrupt kicks it into working again (ie. an unattended reboot could
> > stall).
>
> I have seen this same bug in soft UART IP from "a major vendor."
If you get a chance to try, please let us know if this patch works
there too or needs any additional tweaking to make it work there.
Thanks,
Alex
--
Alex Williamson HP Open Source & Linux Org.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] 8250 UART backup timer
2006-06-27 19:15 ` H. Peter Anvin
2006-06-27 19:32 ` Alex Williamson
@ 2006-09-13 20:18 ` Aristeu Sergio Rozanski Filho
1 sibling, 0 replies; 6+ messages in thread
From: Aristeu Sergio Rozanski Filho @ 2006-09-13 20:18 UTC (permalink / raw)
To: H. Peter Anvin; +Cc: Alex Williamson, rmk+serial, linux-kernel
> Alex Williamson wrote:
> > The patch below works around a minor bug found in the UART of the
> >remote management card used in many HP ia64 and parisc servers (aka the
> >Diva UARTs). The problem is that the UART does not reassert the THRE
> >interrupt if it has been previously cleared and the IIR THRI bit is
> >re-enabled. This can produce a very annoying failure mode when used as
> >a serial console, allowing a boot/reboot to hang indefinitely until an
> >RX interrupt kicks it into working again (ie. an unattended reboot could
> >stall).
> >
> > To solve this problem, a backup timer is introduced that runs
> >alongside the standard interrupt driven mechanism. This timer wakes up
> >periodically, checks for a hang condition and gets characters moving
> >again. This backup mechanism is only enabled if the UART is detected as
> >having this problem, so systems without these UARTs will have no
> >additional overhead.
> >
> > This version of the patch incorporates previous comments from Pavel
> >and removes races in the bug detection code. The test is now done
> >before the irq linking to prevent races with interrupt handler clearing
> >the THRE interrupt. Short delays and syncs are also added to ensure the
> >device is able to update register state before the result is tested.
> >Comments? Thanks,
> >
>
> I have seen this same bug in soft UART IP from "a major vendor."
did you had chance to test this patch on these machines to see if it
solves the problem?
Thanks,
--
Aristeu
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] 8250 UART backup timer
2006-06-27 19:04 [PATCH] 8250 UART backup timer Alex Williamson
2006-06-27 19:15 ` H. Peter Anvin
@ 2006-07-05 3:39 ` Alex Williamson
2006-09-13 20:16 ` Aristeu Sergio Rozanski Filho
1 sibling, 1 reply; 6+ messages in thread
From: Alex Williamson @ 2006-07-05 3:39 UTC (permalink / raw)
To: rmk+serial; +Cc: linux-kernel
Ping. Any other comments on this? Thanks,
Alex
On Tue, 2006-06-27 at 13:04 -0600, Alex Williamson wrote:
> The patch below works around a minor bug found in the UART of the
> remote management card used in many HP ia64 and parisc servers (aka the
> Diva UARTs). The problem is that the UART does not reassert the THRE
> interrupt if it has been previously cleared and the IIR THRI bit is
> re-enabled. This can produce a very annoying failure mode when used as
> a serial console, allowing a boot/reboot to hang indefinitely until an
> RX interrupt kicks it into working again (ie. an unattended reboot could
> stall).
>
> To solve this problem, a backup timer is introduced that runs
> alongside the standard interrupt driven mechanism. This timer wakes up
> periodically, checks for a hang condition and gets characters moving
> again. This backup mechanism is only enabled if the UART is detected as
> having this problem, so systems without these UARTs will have no
> additional overhead.
>
> This version of the patch incorporates previous comments from Pavel
> and removes races in the bug detection code. The test is now done
> before the irq linking to prevent races with interrupt handler clearing
> the THRE interrupt. Short delays and syncs are also added to ensure the
> device is able to update register state before the result is tested.
> Comments? Thanks,
>
> Alex
>
> Signed-off-by: Alex Williamson <alex.williamson@hp.com>
> ---
>
> diff -r e3554576c29a drivers/serial/8250.c
> --- a/drivers/serial/8250.c Sun Jun 18 02:00:07 2006 +0000
> +++ b/drivers/serial/8250.c Tue Jun 27 12:27:03 2006 -0600
> @@ -353,6 +353,23 @@ serial_out(struct uart_8250_port *up, in
> }
> }
>
> +static void
> +serial_out_sync(struct uart_8250_port *up, int offset, int value)
> +{
> + switch (up->port.iotype) {
> + case UPIO_MEM:
> + case UPIO_MEM32:
> +#ifdef CONFIG_SERIAL_8250_AU1X00
> + case UPIO_AU:
> +#endif
> + serial_out(up, offset, value);
> + (void)serial_in(up, UART_LCR); /* safe, no side-effects */
> + break;
> + default:
> + serial_out(up, offset, value);
> + }
> +}
> +
> /*
> * We used to support using pause I/O for certain machines. We
> * haven't supported this for a while, but just in case it's badly
> @@ -1436,6 +1453,13 @@ static void serial_unlink_irq_chain(stru
> serial_do_unlink(i, up);
> }
>
> +/* Base timer interval for polling */
> +static inline int
> +poll_timeout(int timeout)
> +{
> + return timeout > 6 ? (timeout / 2 - 2) : 1;
> +}
> +
> /*
> * This function is used to handle ports that do not have an
> * interrupt. This doesn't work very well for 16450's, but gives
> @@ -1445,16 +1469,52 @@ static void serial8250_timeout(unsigned
> static void serial8250_timeout(unsigned long data)
> {
> struct uart_8250_port *up = (struct uart_8250_port *)data;
> - unsigned int timeout;
> unsigned int iir;
>
> iir = serial_in(up, UART_IIR);
> if (!(iir & UART_IIR_NO_INT))
> serial8250_handle_port(up, NULL);
>
> - timeout = up->port.timeout;
> - timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
> - mod_timer(&up->timer, jiffies + timeout);
> + mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
> +}
> +
> +static void serial8250_backup_timeout(unsigned long data)
> +{
> + struct uart_8250_port *up = (struct uart_8250_port *)data;
> + unsigned int iir, ier = 0;
> +
> + /*
> + * Must disable interrupts or else we risk racing with the interrupt
> + * based handler.
> + */
> + if (is_real_interrupt(up->port.irq)) {
> + ier = serial_in(up, UART_IER);
> + serial_out(up, UART_IER, 0);
> + }
> +
> + iir = serial_in(up, UART_IIR);
> +
> + /*
> + * This should be a safe test for anyone who doesn't trust the
> + * IIR bits on their UART, but it's specifically designed for
> + * the "Diva" UART used on the management processor on many HP
> + * ia64 and parisc boxes.
> + */
> + if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
> + (!uart_circ_empty(&up->port.info->xmit) || up->port.x_char) &&
> + (serial_in(up, UART_LSR) & UART_LSR_THRE)) {
> + iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
> + iir |= UART_IIR_THRI;
> + }
> +
> + if (!(iir & UART_IIR_NO_INT))
> + serial8250_handle_port(up, NULL);
> +
> + if (is_real_interrupt(up->port.irq))
> + serial_out(up, UART_IER, ier);
> +
> + /* Standard timer interval plus 0.2s to keep the port running */
> + mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout) + HZ/5);
> }
>
> static unsigned int serial8250_tx_empty(struct uart_port *port)
> @@ -1523,6 +1583,36 @@ static void serial8250_break_ctl(struct
> up->lcr &= ~UART_LCR_SBC;
> serial_out(up, UART_LCR, up->lcr);
> spin_unlock_irqrestore(&up->port.lock, flags);
> +}
> +
> +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
> +
> +/*
> + * Wait for transmitter & holding register to empty
> + */
> +static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
> +{
> + unsigned int status, timeout = 10000;
> +
> + /* Wait up to 10ms for the character(s) to be sent. */
> + do {
> + status = serial_in(up, UART_LSR);
> +
> + if (status & UART_LSR_BI)
> + up->lsr_break_flag = UART_LSR_BI;
> +
> + if (--timeout == 0)
> + break;
> + udelay(1);
> + } while ((status & bits) != bits);
> +
> + /* Wait up to 1s for flow control if necessary */
> + if (up->port.flags & UPF_CONS_FLOW) {
> + timeout = 1000000;
> + while (--timeout &&
> + ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
> + udelay(1);
> + }
> }
>
> static int serial8250_startup(struct uart_port *port)
> @@ -1598,18 +1688,50 @@ static int serial8250_startup(struct uar
> serial_outp(up, UART_LCR, 0);
> }
>
> + if (is_real_interrupt(up->port.irq)) {
> + /*
> + * Test for UARTs that do not reassert THRE when the
> + * transmitter is idle and the interrupt has already
> + * been cleared. Real 16550s should always reassert
> + * this interrupt whenever the transmitter is idle and
> + * the interrupt is enabled. Delays are necessary to
> + * allow register changes to become visible.
> + */
> + spin_lock_irqsave(&up->port.lock, flags);
> +
> + wait_for_xmitr(up, UART_LSR_THRE);
> + serial_out_sync(up, UART_IER, UART_IER_THRI);
> + udelay(1); /* allow THRE to set */
> + (void)serial_in(up, UART_IIR);
> + serial_out(up, UART_IER, 0);
> + serial_out_sync(up, UART_IER, UART_IER_THRI);
> + udelay(1); /* allow a working UART time to re-assert THRE */
> + iir = serial_in(up, UART_IIR);
> + serial_out(up, UART_IER, 0);
> +
> + spin_unlock_irqrestore(&up->port.lock, flags);
> +
> + /*
> + * If the interrupt is not reasserted, setup a timer to
> + * kick the UART on a regular basis.
> + */
> + if (iir & UART_IIR_NO_INT) {
> + pr_debug("ttyS%d - using backup timer\n", port->line);
> + up->timer.function = serial8250_backup_timeout;
> + up->timer.data = (unsigned long)up;
> + mod_timer(&up->timer, jiffies +
> + poll_timeout(up->port.timeout) + HZ/5);
> + }
> + }
> +
> /*
> * If the "interrupt" for this port doesn't correspond with any
> * hardware interrupt, we use a timer-based system. The original
> * driver used to do this with IRQ0.
> */
> if (!is_real_interrupt(up->port.irq)) {
> - unsigned int timeout = up->port.timeout;
> -
> - timeout = timeout > 6 ? (timeout / 2 - 2) : 1;
> -
> up->timer.data = (unsigned long)up;
> - mod_timer(&up->timer, jiffies + timeout);
> + mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
> } else {
> retval = serial_link_irq_chain(up);
> if (retval)
> @@ -1725,9 +1847,9 @@ static void serial8250_shutdown(struct u
> */
> (void) serial_in(up, UART_RX);
>
> - if (!is_real_interrupt(up->port.irq))
> - del_timer_sync(&up->timer);
> - else
> + del_timer_sync(&up->timer);
> + up->timer.function = serial8250_timeout;
> + if (is_real_interrupt(up->port.irq))
> serial_unlink_irq_chain(up);
> }
>
> @@ -2187,36 +2309,6 @@ serial8250_register_ports(struct uart_dr
>
> #ifdef CONFIG_SERIAL_8250_CONSOLE
>
> -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
> -
> -/*
> - * Wait for transmitter & holding register to empty
> - */
> -static inline void wait_for_xmitr(struct uart_8250_port *up, int bits)
> -{
> - unsigned int status, tmout = 10000;
> -
> - /* Wait up to 10ms for the character(s) to be sent. */
> - do {
> - status = serial_in(up, UART_LSR);
> -
> - if (status & UART_LSR_BI)
> - up->lsr_break_flag = UART_LSR_BI;
> -
> - if (--tmout == 0)
> - break;
> - udelay(1);
> - } while ((status & bits) != bits);
> -
> - /* Wait up to 1s for flow control if necessary */
> - if (up->port.flags & UPF_CONS_FLOW) {
> - tmout = 1000000;
> - while (--tmout &&
> - ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0))
> - udelay(1);
> - }
> -}
> -
> static void serial8250_console_putchar(struct uart_port *port, int ch)
> {
> struct uart_8250_port *up = (struct uart_8250_port *)port;
>
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
--
Alex Williamson HP Open Source & Linux Org.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2006-09-13 20:18 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-27 19:04 [PATCH] 8250 UART backup timer Alex Williamson
2006-06-27 19:15 ` H. Peter Anvin
2006-06-27 19:32 ` Alex Williamson
2006-09-13 20:18 ` Aristeu Sergio Rozanski Filho
2006-07-05 3:39 ` Alex Williamson
2006-09-13 20:16 ` Aristeu Sergio Rozanski Filho
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox