Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 325725
b: refs/heads/master
c: 72256cb
h: refs/heads/master
i:
  325723: 3ff21fa
v: v3
  • Loading branch information
Felipe Balbi authored and Greg Kroah-Hartman committed Sep 6, 2012
1 parent 95f9d87 commit a9c8cff
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 105 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 81b75aef11abfd7b51e719a5388189eefa82e997
refs/heads/master: 72256cbd13904d4b4dbb16f5ec83a3293bb292c5
205 changes: 101 additions & 104 deletions trunk/drivers/tty/serial/omap-serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,74 +196,6 @@ static void serial_omap_stop_rx(struct uart_port *port)
pm_runtime_put_autosuspend(up->dev);
}

static inline void receive_chars(struct uart_omap_port *up,
unsigned int *status)
{
struct tty_struct *tty = up->port.state->port.tty;
unsigned int flag, lsr = *status;
unsigned char ch = 0;
int max_count = 256;

do {
if (likely(lsr & UART_LSR_DR))
ch = serial_in(up, UART_RX);
flag = TTY_NORMAL;
up->port.icount.rx++;

if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
/*
* For statistics only
*/
if (lsr & UART_LSR_BI) {
lsr &= ~(UART_LSR_FE | UART_LSR_PE);
up->port.icount.brk++;
/*
* We do the SysRQ and SAK checking
* here because otherwise the break
* may get masked by ignore_status_mask
* or read_status_mask.
*/
if (uart_handle_break(&up->port))
goto ignore_char;
} else if (lsr & UART_LSR_PE) {
up->port.icount.parity++;
} else if (lsr & UART_LSR_FE) {
up->port.icount.frame++;
}

if (lsr & UART_LSR_OE)
up->port.icount.overrun++;

/*
* Mask off conditions which should be ignored.
*/
lsr &= up->port.read_status_mask;

#ifdef CONFIG_SERIAL_OMAP_CONSOLE
if (up->port.line == up->port.cons->index) {
/* Recover the break flag from console xmit */
lsr |= up->lsr_break_flag;
}
#endif
if (lsr & UART_LSR_BI)
flag = TTY_BREAK;
else if (lsr & UART_LSR_PE)
flag = TTY_PARITY;
else if (lsr & UART_LSR_FE)
flag = TTY_FRAME;
}

if (uart_handle_sysrq_char(&up->port, ch))
goto ignore_char;
uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
ignore_char:
lsr = serial_in(up, UART_LSR);
} while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
spin_lock(&up->port.lock);
}

static void transmit_chars(struct uart_omap_port *up)
{
struct circ_buf *xmit = &up->port.state->xmit;
Expand Down Expand Up @@ -342,6 +274,68 @@ static unsigned int check_modem_status(struct uart_omap_port *up)
return status;
}

static void serial_omap_rlsi(struct uart_omap_port *up, unsigned int lsr)
{
unsigned int flag;

up->port.icount.rx++;
flag = TTY_NORMAL;

if (lsr & UART_LSR_BI) {
flag = TTY_BREAK;
lsr &= ~(UART_LSR_FE | UART_LSR_PE);
up->port.icount.brk++;
/*
* We do the SysRQ and SAK checking
* here because otherwise the break
* may get masked by ignore_status_mask
* or read_status_mask.
*/
if (uart_handle_break(&up->port))
return;

}

if (lsr & UART_LSR_PE) {
flag = TTY_PARITY;
up->port.icount.parity++;
}

if (lsr & UART_LSR_FE) {
flag = TTY_FRAME;
up->port.icount.frame++;
}

if (lsr & UART_LSR_OE)
up->port.icount.overrun++;

#ifdef CONFIG_SERIAL_OMAP_CONSOLE
if (up->port.line == up->port.cons->index) {
/* Recover the break flag from console xmit */
lsr |= up->lsr_break_flag;
}
#endif
uart_insert_char(&up->port, lsr, UART_LSR_OE, 0, flag);
}

static void serial_omap_rdi(struct uart_omap_port *up, unsigned int lsr)
{
unsigned char ch = 0;
unsigned int flag;

if (!(lsr & UART_LSR_DR))
return;

ch = serial_in(up, UART_RX);
flag = TTY_NORMAL;
up->port.icount.rx++;

if (uart_handle_sysrq_char(&up->port, ch))
return;

uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
}

/**
* serial_omap_irq() - This handles the interrupt from one port
* @irq: uart port irq number
Expand All @@ -350,54 +344,57 @@ static unsigned int check_modem_status(struct uart_omap_port *up)
static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
{
struct uart_omap_port *up = dev_id;
struct tty_struct *tty = up->port.state->port.tty;
unsigned int iir, lsr;
unsigned int type;
unsigned long flags;
irqreturn_t ret = IRQ_NONE;
int max_count = 256;

spin_lock_irqsave(&up->port.lock, flags);
pm_runtime_get_sync(up->dev);
iir = serial_in(up, UART_IIR);
again:
if (iir & UART_IIR_NO_INT)
goto out;

ret = IRQ_HANDLED;
lsr = serial_in(up, UART_LSR);
do {
iir = serial_in(up, UART_IIR);
if (iir & UART_IIR_NO_INT)
break;

/* extract IRQ type from IIR register */
type = iir & 0x3e;
ret = IRQ_HANDLED;
lsr = serial_in(up, UART_LSR);

switch (type) {
case UART_IIR_MSI:
check_modem_status(up);
break;
case UART_IIR_THRI:
if (lsr & UART_LSR_THRE)
transmit_chars(up);
break;
case UART_IIR_RDI:
if (lsr & UART_LSR_DR)
receive_chars(up, &lsr);
break;
case UART_IIR_RLSI:
if (lsr & UART_LSR_BRK_ERROR_BITS)
receive_chars(up, &lsr);
break;
case UART_IIR_RX_TIMEOUT:
receive_chars(up, &lsr);
break;
case UART_IIR_CTS_RTS_DSR:
iir = serial_in(up, UART_IIR);
goto again;
case UART_IIR_XOFF:
/* FALLTHROUGH */
default:
break;
}
/* extract IRQ type from IIR register */
type = iir & 0x3e;

switch (type) {
case UART_IIR_MSI:
check_modem_status(up);
break;
case UART_IIR_THRI:
if (lsr & UART_LSR_THRE)
transmit_chars(up);
break;
case UART_IIR_RX_TIMEOUT:
/* FALLTHROUGH */
case UART_IIR_RDI:
serial_omap_rdi(up, lsr);
break;
case UART_IIR_RLSI:
serial_omap_rlsi(up, lsr);
break;
case UART_IIR_CTS_RTS_DSR:
/* simply try again */
break;
case UART_IIR_XOFF:
/* FALLTHROUGH */
default:
break;
}
} while (!(iir & UART_IIR_NO_INT) && max_count--);

out:
spin_unlock_irqrestore(&up->port.lock, flags);

tty_flip_buffer_push(tty);

pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
up->port_activity = jiffies;
Expand Down

0 comments on commit a9c8cff

Please sign in to comment.