mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-27 17:18:59 +00:00
7d7aa2fd92
This change makes the names of Broadcom targets consistent by using the common notation based on SoC/CPU ID (which is used internally anyway), bcmXXXX instead of brcmXXXX. This is even used for target TITLE in make menuconfig already, only the short target name used brcm so far. Despite, since subtargets range from bcm2708 to bcm2711, it seems appropriate to use bcm27xx instead of bcm2708 (again, as already done for BOARDNAME). This also renames the packages brcm2708-userland and brcm2708-gpu-fw. Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de> Acked-by: Álvaro Fernández Rojas <noltari@gmail.com>
86 lines
3.1 KiB
Diff
86 lines
3.1 KiB
Diff
From 3e3c13488e4efa0236c47a98ee5e759bf1f7c757 Mon Sep 17 00:00:00 2001
|
|
From: Phil Elwell <phil@raspberrypi.org>
|
|
Date: Thu, 11 Jul 2019 13:13:39 +0100
|
|
Subject: [PATCH] tty: amba-pl011: Make TX optimisation conditional
|
|
|
|
pl011_tx_chars takes a "from_irq" parameter to reduce the number of
|
|
register accesses. When from_irq is true the function assumes that the
|
|
FIFO is half empty and writes up to half a FIFO's worth of bytes
|
|
without polling the FIFO status register, the reasoning being that
|
|
the function is being called as a result of the TX interrupt being
|
|
raised. This logic would work were it not for the fact that
|
|
pl011_rx_chars, called from pl011_int before pl011_tx_chars, releases
|
|
the spinlock before calling tty_flip_buffer_push.
|
|
|
|
A user thread writing to the UART claims the spinlock and ultimately
|
|
calls pl011_tx_chars with from_irq set to false. This reverts to the
|
|
older logic that polls the FIFO status register before sending every
|
|
byte. If this happen on an SMP system during the section of the IRQ
|
|
handler where the spinlock has been released, then by the time the TX
|
|
interrupt handler is called, the FIFO may already be full, and any
|
|
further writes are likely to be lost.
|
|
|
|
The fix involves adding a per-port flag that is true iff running from
|
|
within the interrupt handler and the spinlock has not yet been released.
|
|
This flag is then used as the value for the from_irq parameter of
|
|
pl011_tx_chars, causing polling to be used in the unsafe case.
|
|
|
|
Fixes: 1e84d22322ce ("serial/amba-pl011: Refactor and simplify TX FIFO handling")
|
|
|
|
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
|
|
---
|
|
drivers/tty/serial/amba-pl011.c | 7 ++++++-
|
|
1 file changed, 6 insertions(+), 1 deletion(-)
|
|
|
|
--- a/drivers/tty/serial/amba-pl011.c
|
|
+++ b/drivers/tty/serial/amba-pl011.c
|
|
@@ -270,6 +270,7 @@ struct uart_amba_port {
|
|
unsigned int old_cr; /* state during shutdown */
|
|
unsigned int fixed_baud; /* vendor-set fixed baud rate */
|
|
char type[12];
|
|
+ bool irq_locked; /* in irq, unreleased lock */
|
|
#ifdef CONFIG_DMA_ENGINE
|
|
/* DMA stuff */
|
|
bool using_tx_dma;
|
|
@@ -813,6 +814,7 @@ __acquires(&uap->port.lock)
|
|
if (!uap->using_tx_dma)
|
|
return;
|
|
|
|
+ uap->irq_locked = 0;
|
|
dmaengine_terminate_async(uap->dmatx.chan);
|
|
|
|
if (uap->dmatx.queued) {
|
|
@@ -939,6 +941,7 @@ static void pl011_dma_rx_chars(struct ua
|
|
fifotaken = pl011_fifo_to_tty(uap);
|
|
}
|
|
|
|
+ uap->irq_locked = 0;
|
|
spin_unlock(&uap->port.lock);
|
|
dev_vdbg(uap->port.dev,
|
|
"Took %d chars from DMA buffer and %d chars from the FIFO\n",
|
|
@@ -1347,6 +1350,7 @@ __acquires(&uap->port.lock)
|
|
{
|
|
pl011_fifo_to_tty(uap);
|
|
|
|
+ uap->irq_locked = 0;
|
|
spin_unlock(&uap->port.lock);
|
|
tty_flip_buffer_push(&uap->port.state->port);
|
|
/*
|
|
@@ -1482,6 +1486,7 @@ static irqreturn_t pl011_int(int irq, vo
|
|
int handled = 0;
|
|
|
|
spin_lock_irqsave(&uap->port.lock, flags);
|
|
+ uap->irq_locked = 1;
|
|
status = pl011_read(uap, REG_RIS) & uap->im;
|
|
if (status) {
|
|
do {
|
|
@@ -1501,7 +1506,7 @@ static irqreturn_t pl011_int(int irq, vo
|
|
UART011_CTSMIS|UART011_RIMIS))
|
|
pl011_modem_status(uap);
|
|
if (status & UART011_TXIS)
|
|
- pl011_tx_chars(uap, true);
|
|
+ pl011_tx_chars(uap, uap->irq_locked);
|
|
|
|
if (pass_counter-- == 0)
|
|
break;
|