lkml.org 
[lkml]   [2012]   [Feb]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    Subject[PATCH] Clear previous interrupts after fifo is disabled
    From
    This is another workaroud of  'https://lkml.org/lkml/2012/1/17/104'
    with additional analysis.Bootloader can transfer control to kernel and
    there are some pending interrupts. In this case, RXFE of the flag
    register is set by clearing FEN(LCRH) even if rx data remains in the
    fifo. It seems that the fifo's status is initiailized. Interrupt
    handler can not get any data from data register because of the below
    break condtion.

    pl011_fifo_to_tty
    while (max_count--) {
    if (status & UART01x_FR_RXFE)
    break;

    Then, Rx interrupt is never cleared. cpu is looping in ISR. System is
    hang. If we don't guarantee that no interrupt is pended until fifo is
    disabled by calling 'writew(0, uap->port.membase + uap->lcrh_rx)',
    this misbehave of the interrupt handelr can be occurred. So, All
    pending interrupts should be cleared just after fifo is disabled under
    the protection from interrupt. Also,'clear error interrupts' routine
    can be removed becuase all interrupts are cleared before.

    Signed-off-by: Chanho Min <chanho.min@lge.com>
    ---
    drivers/tty/serial/amba-pl011.c | 8 ++++----
    1 files changed, 4 insertions(+), 4 deletions(-)

    diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
    index 6800f5f..8b5a824 100644
    --- a/drivers/tty/serial/amba-pl011.c
    +++ b/drivers/tty/serial/amba-pl011.c
    @@ -1397,7 +1397,11 @@ static int pl011_startup(struct uart_port *port)
    writew(cr, uap->port.membase + UART011_CR);
    writew(0, uap->port.membase + UART011_FBRD);
    writew(1, uap->port.membase + UART011_IBRD);
    + spin_lock_irq(&uap->port.lock);
    writew(0, uap->port.membase + uap->lcrh_rx);
    + /* Clear all pending interrupts. */
    + writew(0xffff, uap->port.membase + UART011_ICR);
    + spin_unlock_irq(&uap->port.lock);
    if (uap->lcrh_tx != uap->lcrh_rx) {
    int i;
    /*
    @@ -1417,10 +1421,6 @@ static int pl011_startup(struct uart_port *port)
    cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
    writew(cr, uap->port.membase + UART011_CR);

    - /* Clear pending error interrupts */
    - writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
    - uap->port.membase + UART011_ICR);
    -
    /*
    * initialise the old status of the modem signals
    */
    --
    1.7.0.4

    \
     
     \ /
      Last update: 2012-02-27 10:33    [W:0.026 / U:61.176 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site