net: ppp: Avoid wrapping each byte in muxing headers

When PPP is muxed, using uart_poll_out resulted in each byte getting
wrapped in a muxing header. This led to UART bombardment which
can quickly cause some modems to hang and panic. This was observed
regularly using a SIMCOM7600E modem.

A perfect fix would involve rewriting ppp.c, uart_mux.c and
modem_iface_uart.c to all use another UART API, but that would be more
invasive by several orders of magnitude than this one, which utilizes
the fact that the uart_mux implementation of uart_fifo_fill does NOT
require ISR context. Since the Zephyr UART API states that the behavior
of uart_fifo_fill outside of ISR context is implementation defined, this
should be kosher.

Signed-off-by: Benjamin Lindqvist <benjamin.lindqvist@endian.se>
This commit is contained in:
Benjamin Lindqvist 2020-10-15 14:10:08 +02:00 committed by Carles Cufí
commit 449fc7bb1c
3 changed files with 45 additions and 5 deletions

View file

@ -125,6 +125,18 @@ static int modem_iface_uart_read(struct modem_iface *iface,
return 0;
}
static bool mux_is_active(struct modem_iface *iface)
{
bool active = false;
#if defined(CONFIG_UART_MUX_DEVICE_NAME)
const char *mux_name = CONFIG_UART_MUX_DEVICE_NAME;
active = (mux_name == iface->dev->name);
#endif /* CONFIG_UART_MUX_DEVICE_NAME */
return active;
}
static int modem_iface_uart_write(struct modem_iface *iface,
const uint8_t *buf, size_t size)
{
@ -136,9 +148,18 @@ static int modem_iface_uart_write(struct modem_iface *iface,
return 0;
}
do {
uart_poll_out(iface->dev, *buf++);
} while (--size);
/* If we're using gsm_mux, We don't want to use poll_out because sending
* one byte at a time causes each byte to get wrapped in muxing headers.
* But we can safely call uart_fifo_fill outside of ISR context when
* muxing because uart_mux implements it in software.
*/
if (mux_is_active(iface)) {
uart_fifo_fill(iface->dev, buf, size);
} else {
do {
uart_poll_out(iface->dev, *buf++);
} while (--size);
}
return 0;
}