Merge tag 'tty-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull TTY updates from Greg Kroah-Hartman:
 "Here's the big TTY/serial driver pull request for the 3.5-rc1 merge
  window.

  Nothing major in here, just lots of incremental changes from Alan and
  Jiri reworking some tty core things to behave better and to get a more
  solid grasp on some of the nasty tty locking issues.

  There are a few tty and serial driver updates in here as well.

  All of this has been in the linux-next releases for a while with no
  problems.

  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"

* tag 'tty-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (115 commits)
  serial: bfin_uart: Make MMR access compatible with 32 bits bf609 style controller.
  serial: bfin_uart: RTS and CTS MMRs can be either 16-bit width or 32-bit width.
  serial: bfin_uart: narrow the reboot condition in DMA tx interrupt
  serial: bfin_uart: Adapt bf5xx serial driver to bf60x serial4 controller.
  Revert "serial_core: Update buffer overrun statistics."
  tty: hvc_xen: NULL dereference on allocation failure
  tty: Fix LED error return
  tty: Allow uart_register/unregister/register
  tty: move global ldisc idle waitqueue to the individual ldisc
  serial8250-em: Add DT support
  serial8250-em: clk_get() IS_ERR() error handling fix
  serial_core: Update buffer overrun statistics.
  tty: drop the pty lock during hangup
  cris: fix missing tty arg in wait_event_interruptible_tty call
  tty/amiserial: Add missing argument for tty_unlock()
  tty_lock: Localise the lock
  pty: Lock the devpts bits privately
  tty_lock: undo the old tty_lock use on the ctty
  serial8250-em: Emma Mobile UART driver V2
  Add missing call to uart_update_timeout()
  ...
This commit is contained in:
Linus Torvalds
2012-05-22 16:12:24 -07:00
67 changed files with 1899 additions and 1979 deletions

View File

@@ -68,30 +68,6 @@
#define UART_DR_ERROR (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE)
#define UART_DUMMY_DR_RX (1 << 16)
#define UART_WA_SAVE_NR 14
static void pl011_lockup_wa(unsigned long data);
static const u32 uart_wa_reg[UART_WA_SAVE_NR] = {
ST_UART011_DMAWM,
ST_UART011_TIMEOUT,
ST_UART011_LCRH_RX,
UART011_IBRD,
UART011_FBRD,
ST_UART011_LCRH_TX,
UART011_IFLS,
ST_UART011_XFCR,
ST_UART011_XON1,
ST_UART011_XON2,
ST_UART011_XOFF1,
ST_UART011_XOFF2,
UART011_CR,
UART011_IMSC
};
static u32 uart_wa_regdata[UART_WA_SAVE_NR];
static DECLARE_TASKLET(pl011_lockup_tlet, pl011_lockup_wa, 0);
/* There is by now at least one vendor with differing details, so handle it */
struct vendor_data {
unsigned int ifls;
@@ -101,6 +77,7 @@ struct vendor_data {
bool oversampling;
bool interrupt_may_hang; /* vendor-specific */
bool dma_threshold;
bool cts_event_workaround;
};
static struct vendor_data vendor_arm = {
@@ -110,6 +87,7 @@ static struct vendor_data vendor_arm = {
.lcrh_rx = UART011_LCRH,
.oversampling = false,
.dma_threshold = false,
.cts_event_workaround = false,
};
static struct vendor_data vendor_st = {
@@ -120,6 +98,7 @@ static struct vendor_data vendor_st = {
.oversampling = true,
.interrupt_may_hang = true,
.dma_threshold = true,
.cts_event_workaround = true,
};
static struct uart_amba_port *amba_ports[UART_NR];
@@ -1055,69 +1034,6 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
#define pl011_dma_flush_buffer NULL
#endif
/*
* pl011_lockup_wa
* This workaround aims to break the deadlock situation
* when after long transfer over uart in hardware flow
* control, uart interrupt registers cannot be cleared.
* Hence uart transfer gets blocked.
*
* It is seen that during such deadlock condition ICR
* don't get cleared even on multiple write. This leads
* pass_counter to decrease and finally reach zero. This
* can be taken as trigger point to run this UART_BT_WA.
*
*/
static void pl011_lockup_wa(unsigned long data)
{
struct uart_amba_port *uap = amba_ports[0];
void __iomem *base = uap->port.membase;
struct circ_buf *xmit = &uap->port.state->xmit;
struct tty_struct *tty = uap->port.state->port.tty;
int buf_empty_retries = 200;
int loop;
/* Stop HCI layer from submitting data for tx */
tty->hw_stopped = 1;
while (!uart_circ_empty(xmit)) {
if (buf_empty_retries-- == 0)
break;
udelay(100);
}
/* Backup registers */
for (loop = 0; loop < UART_WA_SAVE_NR; loop++)
uart_wa_regdata[loop] = readl(base + uart_wa_reg[loop]);
/* Disable UART so that FIFO data is flushed out */
writew(0x00, uap->port.membase + UART011_CR);
/* Soft reset UART module */
if (uap->port.dev->platform_data) {
struct amba_pl011_data *plat;
plat = uap->port.dev->platform_data;
if (plat->reset)
plat->reset();
}
/* Restore registers */
for (loop = 0; loop < UART_WA_SAVE_NR; loop++)
writew(uart_wa_regdata[loop] ,
uap->port.membase + uart_wa_reg[loop]);
/* Initialise the old status of the modem signals */
uap->old_status = readw(uap->port.membase + UART01x_FR) &
UART01x_FR_MODEM_ANY;
if (readl(base + UART011_MIS) & 0x2)
printk(KERN_EMERG "UART_BT_WA: ***FAILED***\n");
/* Start Tx/Rx */
tty->hw_stopped = 0;
}
static void pl011_stop_tx(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
@@ -1246,12 +1162,26 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
unsigned long flags;
unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
int handled = 0;
unsigned int dummy_read;
spin_lock_irqsave(&uap->port.lock, flags);
status = readw(uap->port.membase + UART011_MIS);
if (status) {
do {
if (uap->vendor->cts_event_workaround) {
/* workaround to make sure that all bits are unlocked.. */
writew(0x00, uap->port.membase + UART011_ICR);
/*
* WA: introduce 26ns(1 uart clk) delay before W1C;
* single apb access will incur 2 pclk(133.12Mhz) delay,
* so add 2 dummy reads
*/
dummy_read = readw(uap->port.membase + UART011_ICR);
dummy_read = readw(uap->port.membase + UART011_ICR);
}
writew(status & ~(UART011_TXIS|UART011_RTIS|
UART011_RXIS),
uap->port.membase + UART011_ICR);
@@ -1268,11 +1198,8 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
if (status & UART011_TXIS)
pl011_tx_chars(uap);
if (pass_counter-- == 0) {
if (uap->interrupt_may_hang)
tasklet_schedule(&pl011_lockup_tlet);
if (pass_counter-- == 0)
break;
}
status = readw(uap->port.membase + UART011_MIS);
} while (status != 0);