Skip to content

Commit 29c46ce

Browse files
miroslav-ondrapelwell
authored andcommitted
serial: amba-pl011: Fix RTS handling in RS485 mode
commit 2c1fd53 upstream. Data loss on serial line was observed during communication through serial ports ttyAMA1 and ttyAMA2 interconnected via RS485 transcievers. Both ports are in one BCM2711 (Compute Module CM40) and they share the same interrupt line. The problem is caused by long waiting for tx queue flush in the function pl011_rs485_tx_stop. Udelay or mdelay are used to wait. The function is called from the interrupt handler. If multiple devices share a single interrupt line, late processing of pending interrupts and data loss may occur. When operation of both devices are synchronous, collisions are quite often. This rework is based on the method used in tty/serial/imx.c Use hrtimer instead of udelay and mdelay calls. Replace simple bool variable rs485_tx_started by 4-state variable rs485_tx_state. Tested-by: Lino Sanfilippo <[email protected]> Signed-off-by: Miroslav Ondra <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a107374 commit 29c46ce

File tree

1 file changed

+96
-30
lines changed

1 file changed

+96
-30
lines changed

drivers/tty/serial/amba-pl011.c

Lines changed: 96 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,13 @@ struct pl011_dmatx_data {
262262
bool queued;
263263
};
264264

265+
enum pl011_rs485_tx_state {
266+
OFF,
267+
WAIT_AFTER_RTS,
268+
SEND,
269+
WAIT_AFTER_SEND,
270+
};
271+
265272
/*
266273
* We wrap our port structure around the generic uart_port.
267274
*/
@@ -275,8 +282,10 @@ struct uart_amba_port {
275282
unsigned int fifosize; /* vendor-specific */
276283
unsigned int fixed_baud; /* vendor-set fixed baud rate */
277284
char type[12];
278-
bool rs485_tx_started;
279-
unsigned int rs485_tx_drain_interval; /* usecs */
285+
ktime_t rs485_tx_drain_interval; /* nano */
286+
enum pl011_rs485_tx_state rs485_tx_state;
287+
struct hrtimer trigger_start_tx;
288+
struct hrtimer trigger_stop_tx;
280289
#ifdef CONFIG_DMA_ENGINE
281290
/* DMA stuff */
282291
unsigned int dmacr; /* dma control reg */
@@ -1281,30 +1290,31 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
12811290

12821291
static void pl011_rs485_tx_stop(struct uart_amba_port *uap)
12831292
{
1284-
/*
1285-
* To be on the safe side only time out after twice as many iterations
1286-
* as fifo size.
1287-
*/
1288-
const int MAX_TX_DRAIN_ITERS = uap->port.fifosize * 2;
12891293
struct uart_port *port = &uap->port;
1290-
int i = 0;
12911294
u32 cr;
12921295

1293-
/* Wait until hardware tx queue is empty */
1294-
while (!pl011_tx_empty(port)) {
1295-
if (i > MAX_TX_DRAIN_ITERS) {
1296-
dev_warn(port->dev,
1297-
"timeout while draining hardware tx queue\n");
1298-
break;
1299-
}
1296+
if (uap->rs485_tx_state == SEND)
1297+
uap->rs485_tx_state = WAIT_AFTER_SEND;
13001298

1301-
udelay(uap->rs485_tx_drain_interval);
1302-
i++;
1299+
if (uap->rs485_tx_state == WAIT_AFTER_SEND) {
1300+
/* Schedule hrtimer if tx queue not empty */
1301+
if (!pl011_tx_empty(port)) {
1302+
hrtimer_start(&uap->trigger_stop_tx,
1303+
uap->rs485_tx_drain_interval,
1304+
HRTIMER_MODE_REL);
1305+
return;
1306+
}
1307+
if (port->rs485.delay_rts_after_send > 0) {
1308+
hrtimer_start(&uap->trigger_stop_tx,
1309+
ms_to_ktime(port->rs485.delay_rts_after_send),
1310+
HRTIMER_MODE_REL);
1311+
return;
1312+
}
1313+
/* Continue without any delay */
1314+
} else if (uap->rs485_tx_state == WAIT_AFTER_RTS) {
1315+
hrtimer_try_to_cancel(&uap->trigger_start_tx);
13031316
}
13041317

1305-
if (port->rs485.delay_rts_after_send)
1306-
mdelay(port->rs485.delay_rts_after_send);
1307-
13081318
cr = pl011_read(uap, REG_CR);
13091319

13101320
if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
@@ -1317,19 +1327,26 @@ static void pl011_rs485_tx_stop(struct uart_amba_port *uap)
13171327
cr |= UART011_CR_RXE;
13181328
pl011_write(cr, uap, REG_CR);
13191329

1320-
uap->rs485_tx_started = false;
1330+
uap->rs485_tx_state = OFF;
13211331
}
13221332

13231333
static void pl011_stop_tx(struct uart_port *port)
13241334
{
13251335
struct uart_amba_port *uap =
13261336
container_of(port, struct uart_amba_port, port);
13271337

1338+
if (port->rs485.flags & SER_RS485_ENABLED &&
1339+
uap->rs485_tx_state == WAIT_AFTER_RTS) {
1340+
pl011_rs485_tx_stop(uap);
1341+
return;
1342+
}
1343+
13281344
uap->im &= ~UART011_TXIM;
13291345
pl011_write(uap->im, uap, REG_IMSC);
13301346
pl011_dma_tx_stop(uap);
13311347

1332-
if ((port->rs485.flags & SER_RS485_ENABLED) && uap->rs485_tx_started)
1348+
if (port->rs485.flags & SER_RS485_ENABLED &&
1349+
uap->rs485_tx_state != OFF)
13331350
pl011_rs485_tx_stop(uap);
13341351
}
13351352

@@ -1349,10 +1366,19 @@ static void pl011_rs485_tx_start(struct uart_amba_port *uap)
13491366
struct uart_port *port = &uap->port;
13501367
u32 cr;
13511368

1369+
if (uap->rs485_tx_state == WAIT_AFTER_RTS) {
1370+
uap->rs485_tx_state = SEND;
1371+
return;
1372+
}
1373+
if (uap->rs485_tx_state == WAIT_AFTER_SEND) {
1374+
hrtimer_try_to_cancel(&uap->trigger_stop_tx);
1375+
uap->rs485_tx_state = SEND;
1376+
return;
1377+
}
1378+
/* uap->rs485_tx_state == OFF */
13521379
/* Enable transmitter */
13531380
cr = pl011_read(uap, REG_CR);
13541381
cr |= UART011_CR_TXE;
1355-
13561382
/* Disable receiver if half-duplex */
13571383
if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
13581384
cr &= ~UART011_CR_RXE;
@@ -1364,10 +1390,14 @@ static void pl011_rs485_tx_start(struct uart_amba_port *uap)
13641390

13651391
pl011_write(cr, uap, REG_CR);
13661392

1367-
if (port->rs485.delay_rts_before_send)
1368-
mdelay(port->rs485.delay_rts_before_send);
1369-
1370-
uap->rs485_tx_started = true;
1393+
if (port->rs485.delay_rts_before_send > 0) {
1394+
uap->rs485_tx_state = WAIT_AFTER_RTS;
1395+
hrtimer_start(&uap->trigger_start_tx,
1396+
ms_to_ktime(port->rs485.delay_rts_before_send),
1397+
HRTIMER_MODE_REL);
1398+
} else {
1399+
uap->rs485_tx_state = SEND;
1400+
}
13711401
}
13721402

13731403
static void pl011_start_tx(struct uart_port *port)
@@ -1376,13 +1406,44 @@ static void pl011_start_tx(struct uart_port *port)
13761406
container_of(port, struct uart_amba_port, port);
13771407

13781408
if ((uap->port.rs485.flags & SER_RS485_ENABLED) &&
1379-
!uap->rs485_tx_started)
1409+
uap->rs485_tx_state != SEND) {
13801410
pl011_rs485_tx_start(uap);
1411+
if (uap->rs485_tx_state == WAIT_AFTER_RTS)
1412+
return;
1413+
}
13811414

13821415
if (!pl011_dma_tx_start(uap))
13831416
pl011_start_tx_pio(uap);
13841417
}
13851418

1419+
static enum hrtimer_restart pl011_trigger_start_tx(struct hrtimer *t)
1420+
{
1421+
struct uart_amba_port *uap =
1422+
container_of(t, struct uart_amba_port, trigger_start_tx);
1423+
unsigned long flags;
1424+
1425+
uart_port_lock_irqsave(&uap->port, &flags);
1426+
if (uap->rs485_tx_state == WAIT_AFTER_RTS)
1427+
pl011_start_tx(&uap->port);
1428+
uart_port_unlock_irqrestore(&uap->port, flags);
1429+
1430+
return HRTIMER_NORESTART;
1431+
}
1432+
1433+
static enum hrtimer_restart pl011_trigger_stop_tx(struct hrtimer *t)
1434+
{
1435+
struct uart_amba_port *uap =
1436+
container_of(t, struct uart_amba_port, trigger_stop_tx);
1437+
unsigned long flags;
1438+
1439+
uart_port_lock_irqsave(&uap->port, &flags);
1440+
if (uap->rs485_tx_state == WAIT_AFTER_SEND)
1441+
pl011_rs485_tx_stop(uap);
1442+
uart_port_unlock_irqrestore(&uap->port, flags);
1443+
1444+
return HRTIMER_NORESTART;
1445+
}
1446+
13861447
static void pl011_stop_rx(struct uart_port *port)
13871448
{
13881449
struct uart_amba_port *uap =
@@ -1979,7 +2040,7 @@ static void pl011_shutdown(struct uart_port *port)
19792040

19802041
pl011_dma_shutdown(uap);
19812042

1982-
if ((port->rs485.flags & SER_RS485_ENABLED) && uap->rs485_tx_started)
2043+
if ((port->rs485.flags & SER_RS485_ENABLED && uap->rs485_tx_state != OFF))
19832044
pl011_rs485_tx_stop(uap);
19842045

19852046
free_irq(uap->port.irq, uap);
@@ -2124,7 +2185,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
21242185
* with the given baud rate. We use this as the poll interval when we
21252186
* wait for the tx queue to empty.
21262187
*/
2127-
uap->rs485_tx_drain_interval = DIV_ROUND_UP(bits * 1000 * 1000, baud);
2188+
uap->rs485_tx_drain_interval = ns_to_ktime(DIV_ROUND_UP(bits * NSEC_PER_SEC, baud));
21282189

21292190
pl011_setup_status_masks(port, termios);
21302191

@@ -2838,6 +2899,11 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
28382899
}
28392900
}
28402901

2902+
hrtimer_init(&uap->trigger_start_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
2903+
hrtimer_init(&uap->trigger_stop_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
2904+
uap->trigger_start_tx.function = pl011_trigger_start_tx;
2905+
uap->trigger_stop_tx.function = pl011_trigger_stop_tx;
2906+
28412907
ret = pl011_setup_port(&dev->dev, uap, &dev->res, portnr);
28422908
if (ret)
28432909
return ret;

0 commit comments

Comments
 (0)