lkml.org 
[lkml]   [2012]   [Feb]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
SubjectRe: [PATCH] Clear previous interrupts after fifo is disabled
From
> Which is why my patch explicitly clears the receive interrupt status
> before requesting the interrupt.  Have you read my patch?
This is the hang-up scenario with your patch.

pl011_startup(struct uart_port *port)
uap->port.uartclk = clk_get_rate(uap->clk);

/* Clear pending error and receive interrupts */
writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
...
1. RX Interrupt is occurred after interrupt is cleared. Even if
interrupt is masked/disabled before(or probe time), RIS's Rx interrupt
is set to 1. Of course, masked status is zero.
...
2. RXFE of flag register is zero and fifo is not empty before LCRH is cleared.
writew(0, uap->port.membase + uap->lcrh_rx);
3. RXFE of flag register is changed to '1' after LCRH is cleared. but
the fifo is not actually empty.
...
4. Finally, We enable interrupts.
spin_lock_irq(&uap->port.lock);
uap->im = UART011_RTIM;
if (!pl011_dma_rx_running(uap))
uap->im |= UART011_RXIM;
writew(uap->im, uap->port.membase + UART011_IMSC);
spin_unlock_irq(&uap->port.lock);
5. The RIS's field which is enabled by IMSC is reflected to MIS as
soon as the interrupt enable. (We checked this on our ARM platform )
6. IRQ context is started. pl011_fifo_to_tty is called by pl011_int.
static int pl011_fifo_to_tty(struct uart_amba_port *uap)
...
while (max_count--) {
status = readw(uap->port.membase + UART01x_FR);
if (status & UART01x_FR_RXFE)
break;
...
7. pl011_fifo_to_tty can't read any data from DR because of the break
condition for RXFE. Rx interrupt can't be cleared. cpu is looping in
irq context.

This is why we need to be cleared just after LCRH is cleared not
before irq_request. Let's get back to my patch. Even if data is
received before or after interrupt is cleared, flag register will show
actual fifo status. Interrupt handler runs normally after the uart
operation is started up by enabling interrupt.

+ spin_lock_irq(&uap->port.lock);
writew(0, uap->port.membase + uap->lcrh_rx);
+ /* Clear pending error and receive interrupts */
+ writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
+ UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
+ spin_unlock_irq(&uap->port.lock);

Thanks,
Chanho Min
--
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/

\
 
 \ /
  Last update: 2012-02-29 03:49    [W:0.052 / U:0.040 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site