diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 763eb20..6f5a072 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1249,19 +1249,20 @@ __acquires(&uap->port.lock)

 /*
  * Transmit a character
+ * There must be at least one free entry in the TX FIFO to accept the char.
  *
- * Returns true if the character was successfully queued to the FIFO.
- * Returns false otherwise.
+ * Returns true if the FIFO might have space in it afterwards;
+ * returns false if the FIFO definitely became full.
  */
 static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c)
 {
-       if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
-               return false; /* unable to transmit character */
-
        writew(c, uap->port.membase + UART01x_DR);
        uap->port.icount.tx++;

-       return true;
+       if (likely(uap->tx_irq_seen > 1))
+               return true;
+
+       return !(readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF);
 }

 static bool pl011_tx_chars(struct uart_amba_port *uap)
@@ -1295,8 +1296,7 @@ static bool pl011_tx_chars(struct uart_amba_port *uap)
                return false;

        if (uap->port.x_char) {
-               if (!pl011_tx_char(uap, uap->port.x_char))
-                       goto done;
+               pl011_tx_char(uap, uap->port.x_char);
                uap->port.x_char = 0;
                --count;
        }
--
1.7.10.4

From ece86a450686f37c3761a25c64af013bc556ee61 Mon Sep 17 00:00:00 2001
From: Dave Martin <Dave.Martin@arm.com>
Date: Mon, 15 Jun 2015 14:07:39 +0100
Subject: [REVERT 2/2] Revert "serial/amba-pl011: Activate TX IRQ passively"

This reverts commit 734745caeb9f155ab58918834a8c70e83fa6afd3.

Conflicts:
        drivers/tty/serial/amba-pl011.c
---
 drivers/tty/serial/amba-pl011.c |  165 ++++++++++++---------------------------
 1 file changed, 50 insertions(+), 115 deletions(-)

diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 6f5a072..a9074c0 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -58,7 +58,6 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/sizes.h>
 #include <linux/io.h>
-#include <linux/workqueue.h>

 #define UART_NR                        14

@@ -157,9 +156,7 @@ struct uart_amba_port {
        unsigned int            lcrh_tx;        /* vendor-specific */
        unsigned int            lcrh_rx;        /* vendor-specific */
        unsigned int            old_cr;         /* state during shutdown */
-       struct delayed_work     tx_softirq_work;
        bool                    autorts;
-       unsigned int            tx_irq_seen;    /* 0=none, 1=1, 2=2 or more */
        char                    type[12];
 #ifdef CONFIG_DMA_ENGINE
        /* DMA stuff */
@@ -403,9 +400,8 @@ static void pl011_dma_remove(struct uart_amba_port *uap)
                dma_release_channel(uap->dmarx.chan);
 }

-/* Forward declare these for the refill routine */
+/* Forward declare this for the refill routine */
 static int pl011_dma_tx_refill(struct uart_amba_port *uap);
-static void pl011_start_tx_pio(struct uart_amba_port *uap);

 /*
  * The current DMA TX buffer has been sent.
@@ -443,13 +439,14 @@ static void pl011_dma_tx_callback(void *data)
                return;
        }

-       if (pl011_dma_tx_refill(uap) <= 0)
+       if (pl011_dma_tx_refill(uap) <= 0) {
                /*
                 * We didn't queue a DMA buffer for some reason, but we
                 * have data pending to be sent.  Re-enable the TX IRQ.
                 */
-               pl011_start_tx_pio(uap);
-
+               uap->im |= UART011_TXIM;
+               writew(uap->im, uap->port.membase + UART011_IMSC);
+       }
        spin_unlock_irqrestore(&uap->port.lock, flags);
 }

@@ -627,10 +624,12 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
                if (!uap->dmatx.queued) {
                        if (pl011_dma_tx_refill(uap) > 0) {
                                uap->im &= ~UART011_TXIM;
-                               writew(uap->im, uap->port.membase +
-                                      UART011_IMSC);
-                       } else
+                               ret = true;
+                       } else {
+                               uap->im |= UART011_TXIM;
                                ret = false;
+                       }
+                       writew(uap->im, uap->port.membase + UART011_IMSC);
                } else if (!(uap->dmacr & UART011_TXDMAE)) {
                        uap->dmacr |= UART011_TXDMAE;
                        writew(uap->dmacr,
@@ -1172,24 +1171,15 @@ static void pl011_stop_tx(struct uart_port *port)
        pl011_dma_tx_stop(uap);
 }

-static bool pl011_tx_chars(struct uart_amba_port *uap);
-
-/* Start TX with programmed I/O only (no DMA) */
-static void pl011_start_tx_pio(struct uart_amba_port *uap)
-{
-       uap->im |= UART011_TXIM;
-       writew(uap->im, uap->port.membase + UART011_IMSC);
-       if (!uap->tx_irq_seen)
-               pl011_tx_chars(uap);
-}
-
 static void pl011_start_tx(struct uart_port *port)
 {
        struct uart_amba_port *uap =
            container_of(port, struct uart_amba_port, port);

-       if (!pl011_dma_tx_start(uap))
-               pl011_start_tx_pio(uap);
+       if (!pl011_dma_tx_start(uap)) {
+               uap->im |= UART011_TXIM;
+               writew(uap->im, uap->port.membase + UART011_IMSC);
+       }
 }

 static void pl011_stop_rx(struct uart_port *port)
@@ -1247,87 +1237,40 @@ __acquires(&uap->port.lock)
        spin_lock(&uap->port.lock);
 }

-/*
- * Transmit a character
- * There must be at least one free entry in the TX FIFO to accept the char.
- *
- * Returns true if the FIFO might have space in it afterwards;
- * returns false if the FIFO definitely became full.
- */
-static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c)
-{
-       writew(c, uap->port.membase + UART01x_DR);
-       uap->port.icount.tx++;
-
-       if (likely(uap->tx_irq_seen > 1))
-               return true;
-
-       return !(readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF);
-}
-
-static bool pl011_tx_chars(struct uart_amba_port *uap)
+static void pl011_tx_chars(struct uart_amba_port *uap)
 {
        struct circ_buf *xmit = &uap->port.state->xmit;
        int count;

-       if (unlikely(uap->tx_irq_seen < 2))
-               /*
-                * Initial FIFO fill level unknown: we must check TXFF
-                * after each write, so just try to fill up the FIFO.
-                */
-               count = uap->fifosize;
-       else /* tx_irq_seen >= 2 */
-               /*
-                * FIFO initially at least half-empty, so we can simply
-                * write half the FIFO without polling TXFF.
-
-                * Note: the *first* TX IRQ can still race with
-                * pl011_start_tx_pio(), which can result in the FIFO
-                * being fuller than expected in that case.
-                */
-               count = uap->fifosize >> 1;
-
-       /*
-        * If the FIFO is full we're guaranteed a TX IRQ at some later point,
-        * and can't transmit immediately in any case:
-        */
-       if (unlikely(uap->tx_irq_seen < 2 &&
-                    readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF))
-               return false;
-
        if (uap->port.x_char) {
-               pl011_tx_char(uap, uap->port.x_char);
+               writew(uap->port.x_char, uap->port.membase + UART01x_DR);
+               uap->port.icount.tx++;
                uap->port.x_char = 0;
-               --count;
+               return;
        }
        if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
                pl011_stop_tx(&uap->port);
-               goto done;
+               return;
        }

        /* If we are using DMA mode, try to send some characters. */
        if (pl011_dma_tx_irq(uap))
-               goto done;
+               return;

-       while (count-- > 0 && pl011_tx_char(uap, xmit->buf[xmit->tail])) {
+       count = uap->fifosize >> 1;
+       do {
+               writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               uap->port.icount.tx++;
                if (uart_circ_empty(xmit))
                        break;
-       }
+       } while (--count > 0);

        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(&uap->port);

-       if (uart_circ_empty(xmit)) {
+       if (uart_circ_empty(xmit))
                pl011_stop_tx(&uap->port);
-               goto done;
-       }
-
-       if (unlikely(!uap->tx_irq_seen))
-               schedule_delayed_work(&uap->tx_softirq_work, uap->port.timeout);
-
-done:
-       return false;
 }

 static void pl011_modem_status(struct uart_amba_port *uap)
@@ -1354,28 +1297,6 @@ static void pl011_modem_status(struct uart_amba_port *uap)
        wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
 }

-static void pl011_tx_softirq(struct work_struct *work)
-{
-       struct delayed_work *dwork = to_delayed_work(work);
-       struct uart_amba_port *uap =
-               container_of(dwork, struct uart_amba_port, tx_softirq_work);
-
-       spin_lock(&uap->port.lock);
-       while (pl011_tx_chars(uap)) ;
-       spin_unlock(&uap->port.lock);
-}
-
-static void pl011_tx_irq_seen(struct uart_amba_port *uap)
-{
-       if (likely(uap->tx_irq_seen > 1))
-               return;
-
-       uap->tx_irq_seen++;
-       if (uap->tx_irq_seen < 2)
-               /* first TX IRQ */
-               cancel_delayed_work(&uap->tx_softirq_work);
-}
-
 static irqreturn_t pl011_int(int irq, void *dev_id)
 {
        struct uart_amba_port *uap = dev_id;
@@ -1414,10 +1335,8 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
                        if (status & (UART011_DSRMIS|UART011_DCDMIS|
                                      UART011_CTSMIS|UART011_RIMIS))
                                pl011_modem_status(uap);
-                       if (status & UART011_TXIS) {
-                               pl011_tx_irq_seen(uap);
+                       if (status & UART011_TXIS)
                                pl011_tx_chars(uap);
-                       }

                        if (pass_counter-- == 0)
                                break;
@@ -1621,7 +1540,7 @@ static int pl011_startup(struct uart_port *port)
 {
        struct uart_amba_port *uap =
            container_of(port, struct uart_amba_port, port);
-       unsigned int cr;
+       unsigned int cr, lcr_h, fbrd, ibrd;
        int retval;

        retval = pl011_hwinit(port);
@@ -1639,11 +1558,30 @@ static int pl011_startup(struct uart_port *port)

        writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);

-       /* Assume that TX IRQ doesn't work until we see one: */
-       uap->tx_irq_seen = 0;
-
+       /*
+        * Provoke TX FIFO interrupt into asserting. Taking care to preserve
+        * baud rate and data format specified by FBRD, IBRD and LCRH as the
+        * UART may already be in use as a console.
+        */
        spin_lock_irq(&uap->port.lock);

+       fbrd = readw(uap->port.membase + UART011_FBRD);
+       ibrd = readw(uap->port.membase + UART011_IBRD);
+       lcr_h = readw(uap->port.membase + uap->lcrh_rx);
+
+       cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE;
+       writew(cr, uap->port.membase + UART011_CR);
+       writew(0, uap->port.membase + UART011_FBRD);
+       writew(1, uap->port.membase + UART011_IBRD);
+       pl011_write_lcr_h(uap, 0);
+       writew(0, uap->port.membase + UART01x_DR);
+       while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
+               barrier();
+
+       writew(fbrd, uap->port.membase + UART011_FBRD);
+       writew(ibrd, uap->port.membase + UART011_IBRD);
+       pl011_write_lcr_h(uap, lcr_h);
+
        /* restore RTS and DTR */
        cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
        cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
@@ -1697,8 +1635,6 @@ static void pl011_shutdown(struct uart_port *port)
            container_of(port, struct uart_amba_port, port);
        unsigned int cr;

-       cancel_delayed_work_sync(&uap->tx_softirq_work);
-
        /*
         * disable all interrupts
         */
@@ -2245,7 +2181,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
        uap->port.ops = &amba_pl011_pops;
        uap->port.flags = UPF_BOOT_AUTOCONF;
        uap->port.line = i;
-       INIT_DELAYED_WORK(&uap->tx_softirq_work, pl011_tx_softirq);

        /* Ensure interrupts from this UART are masked and cleared */
        writew(0, uap->port.membase + UART011_IMSC);
