TTY/Serial fixes for 5.16-rc4

Here are some small TTY and Serial driver fixes for 5.16-rc4 to resolve
 a number of reported problems.
 
 They include:
 	- liteuart serial driver fixes
 	- 8250_pci serial driver fixes for pericom devices
 	- 8250 RTS line control fix while in RS-485 mode
 	- tegra serial driver fix
 	- msm_serial driver fix
 	- pl011 serial driver new id
 	- fsl_lpuart revert of broken change
 	- 8250_bcm7271 serial driver fix
 	- MAINTAINERS file update for rpmsg tty driver that came in
 	  5.16-rc1
 	- vgacon fix for reported problem
 
 All of these, except for the 8250_bcm7271 fix have been in linux-next
 with no reported problem.  The 8250_bcm7271 fix was added to the tree on
 Friday so no chance to be linux-next yet.  But it should be fine as the
 affected developers submitted it.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYayo2Q8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+yno+wCguxkicXNPay+HXlDcImmCAXLhc/cAn34AwHP4
 +Lgvooz39wYxzl5D/Qhc
 =tw0u
 -----END PGP SIGNATURE-----

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

Pull tty/serial fixes from Greg KH:
 "Here are some small TTY and Serial driver fixes for 5.16-rc4 to
  resolve a number of reported problems.

  They include:

   - liteuart serial driver fixes

   - 8250_pci serial driver fixes for pericom devices

   - 8250 RTS line control fix while in RS-485 mode

   - tegra serial driver fix

   - msm_serial driver fix

   - pl011 serial driver new id

   - fsl_lpuart revert of broken change

   - 8250_bcm7271 serial driver fix

   - MAINTAINERS file update for rpmsg tty driver that came in 5.16-rc1

   - vgacon fix for reported problem

  All of these, except for the 8250_bcm7271 fix have been in linux-next
  with no reported problem. The 8250_bcm7271 fix was added to the tree
  on Friday so no chance to be linux-next yet. But it should be fine as
  the affected developers submitted it"

* tag 'tty-5.16-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  serial: 8250_bcm7271: UART errors after resuming from S2
  serial: 8250_pci: rewrite pericom_do_set_divisor()
  serial: 8250_pci: Fix ACCES entries in pci_serial_quirks array
  serial: 8250: Fix RTS modem control while in rs485 mode
  Revert "tty: serial: fsl_lpuart: drop earlycon entry for i.MX8QXP"
  serial: tegra: Change lower tolerance baud rate limit for tegra20 and tegra30
  serial: liteuart: relax compile-test dependencies
  serial: liteuart: fix minor-number leak on probe errors
  serial: liteuart: fix use-after-free and memleak on unbind
  serial: liteuart: Fix NULL pointer dereference in ->remove()
  vgacon: Propagate console boot parameters before calling `vc_resize'
  tty: serial: msm_serial: Deactivate RX DMA for polling support
  serial: pl011: Add ACPI SBSA UART match id
  serial: core: fix transmit-buffer reset and memleak
  MAINTAINERS: Add rpmsg tty driver maintainer
This commit is contained in:
Linus Torvalds 2021-12-05 09:13:20 -08:00
commit 5163953950
12 changed files with 95 additions and 33 deletions

View File

@ -16502,6 +16502,12 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/allwinner,sun8i-a83t-de2-rotate.yaml F: Documentation/devicetree/bindings/media/allwinner,sun8i-a83t-de2-rotate.yaml
F: drivers/media/platform/sunxi/sun8i-rotate/ F: drivers/media/platform/sunxi/sun8i-rotate/
RPMSG TTY DRIVER
M: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
L: linux-remoteproc@vger.kernel.org
S: Maintained
F: drivers/tty/rpmsg_tty.c
RTL2830 MEDIA DRIVER RTL2830 MEDIA DRIVER
M: Antti Palosaari <crope@iki.fi> M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org

View File

@ -237,6 +237,7 @@ struct brcmuart_priv {
u32 rx_err; u32 rx_err;
u32 rx_timeout; u32 rx_timeout;
u32 rx_abort; u32 rx_abort;
u32 saved_mctrl;
}; };
static struct dentry *brcmuart_debugfs_root; static struct dentry *brcmuart_debugfs_root;
@ -1133,16 +1134,27 @@ static int brcmuart_remove(struct platform_device *pdev)
static int __maybe_unused brcmuart_suspend(struct device *dev) static int __maybe_unused brcmuart_suspend(struct device *dev)
{ {
struct brcmuart_priv *priv = dev_get_drvdata(dev); struct brcmuart_priv *priv = dev_get_drvdata(dev);
struct uart_8250_port *up = serial8250_get_port(priv->line);
struct uart_port *port = &up->port;
serial8250_suspend_port(priv->line); serial8250_suspend_port(priv->line);
clk_disable_unprepare(priv->baud_mux_clk); clk_disable_unprepare(priv->baud_mux_clk);
/*
* This will prevent resume from enabling RTS before the
* baud rate has been resored.
*/
priv->saved_mctrl = port->mctrl;
port->mctrl = 0;
return 0; return 0;
} }
static int __maybe_unused brcmuart_resume(struct device *dev) static int __maybe_unused brcmuart_resume(struct device *dev)
{ {
struct brcmuart_priv *priv = dev_get_drvdata(dev); struct brcmuart_priv *priv = dev_get_drvdata(dev);
struct uart_8250_port *up = serial8250_get_port(priv->line);
struct uart_port *port = &up->port;
int ret; int ret;
ret = clk_prepare_enable(priv->baud_mux_clk); ret = clk_prepare_enable(priv->baud_mux_clk);
@ -1165,6 +1177,7 @@ static int __maybe_unused brcmuart_resume(struct device *dev)
start_rx_dma(serial8250_get_port(priv->line)); start_rx_dma(serial8250_get_port(priv->line));
} }
serial8250_resume_port(priv->line); serial8250_resume_port(priv->line);
port->mctrl = priv->saved_mctrl;
return 0; return 0;
} }

View File

@ -1324,29 +1324,33 @@ pericom_do_set_divisor(struct uart_port *port, unsigned int baud,
{ {
int scr; int scr;
int lcr; int lcr;
int actual_baud;
int tolerance;
for (scr = 5 ; scr <= 15 ; scr++) { for (scr = 16; scr > 4; scr--) {
actual_baud = 921600 * 16 / scr; unsigned int maxrate = port->uartclk / scr;
tolerance = actual_baud / 50; unsigned int divisor = max(maxrate / baud, 1U);
int delta = maxrate / divisor - baud;
if ((baud < actual_baud + tolerance) && if (baud > maxrate + baud / 50)
(baud > actual_baud - tolerance)) { continue;
if (delta > baud / 50)
divisor++;
if (divisor > 0xffff)
continue;
/* Update delta due to possible divisor change */
delta = maxrate / divisor - baud;
if (abs(delta) < baud / 50) {
lcr = serial_port_in(port, UART_LCR); lcr = serial_port_in(port, UART_LCR);
serial_port_out(port, UART_LCR, lcr | 0x80); serial_port_out(port, UART_LCR, lcr | 0x80);
serial_port_out(port, UART_DLL, divisor & 0xff);
serial_port_out(port, UART_DLL, 1); serial_port_out(port, UART_DLM, divisor >> 8 & 0xff);
serial_port_out(port, UART_DLM, 0);
serial_port_out(port, 2, 16 - scr); serial_port_out(port, 2, 16 - scr);
serial_port_out(port, UART_LCR, lcr); serial_port_out(port, UART_LCR, lcr);
return; return;
} else if (baud > actual_baud) {
break;
} }
} }
serial8250_do_set_divisor(port, baud, quot, quot_frac);
} }
static int pci_pericom_setup(struct serial_private *priv, static int pci_pericom_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
@ -2291,12 +2295,19 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
.setup = pci_pericom_setup_four_at_eight, .setup = pci_pericom_setup_four_at_eight,
}, },
{ {
.vendor = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, .vendor = PCI_VENDOR_ID_ACCESIO,
.device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4, .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.setup = pci_pericom_setup_four_at_eight, .setup = pci_pericom_setup_four_at_eight,
}, },
{
.vendor = PCI_VENDOR_ID_ACCESIO,
.device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_pericom_setup_four_at_eight,
},
{ {
.vendor = PCI_VENDOR_ID_ACCESIO, .vendor = PCI_VENDOR_ID_ACCESIO,
.device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4, .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4,

View File

@ -2024,13 +2024,6 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
struct uart_8250_port *up = up_to_u8250p(port); struct uart_8250_port *up = up_to_u8250p(port);
unsigned char mcr; unsigned char mcr;
if (port->rs485.flags & SER_RS485_ENABLED) {
if (serial8250_in_MCR(up) & UART_MCR_RTS)
mctrl |= TIOCM_RTS;
else
mctrl &= ~TIOCM_RTS;
}
mcr = serial8250_TIOCM_to_MCR(mctrl); mcr = serial8250_TIOCM_to_MCR(mctrl);
mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;

View File

@ -1533,7 +1533,7 @@ config SERIAL_LITEUART
tristate "LiteUART serial port support" tristate "LiteUART serial port support"
depends on HAS_IOMEM depends on HAS_IOMEM
depends on OF || COMPILE_TEST depends on OF || COMPILE_TEST
depends on LITEX depends on LITEX || COMPILE_TEST
select SERIAL_CORE select SERIAL_CORE
help help
This driver is for the FPGA-based LiteUART serial controller from LiteX This driver is for the FPGA-based LiteUART serial controller from LiteX

View File

@ -2947,6 +2947,7 @@ MODULE_DEVICE_TABLE(of, sbsa_uart_of_match);
static const struct acpi_device_id __maybe_unused sbsa_uart_acpi_match[] = { static const struct acpi_device_id __maybe_unused sbsa_uart_acpi_match[] = {
{ "ARMH0011", 0 }, { "ARMH0011", 0 },
{ "ARMHB000", 0 },
{}, {},
}; };
MODULE_DEVICE_TABLE(acpi, sbsa_uart_acpi_match); MODULE_DEVICE_TABLE(acpi, sbsa_uart_acpi_match);

View File

@ -2625,6 +2625,7 @@ OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup); OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup);
OF_EARLYCON_DECLARE(lpuart32, "fsl,imx8qxp-lpuart", lpuart32_imx_early_console_setup);
EARLYCON_DECLARE(lpuart, lpuart_early_console_setup); EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);
EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup); EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup);

View File

@ -270,8 +270,10 @@ static int liteuart_probe(struct platform_device *pdev)
/* get membase */ /* get membase */
port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(port->membase)) if (IS_ERR(port->membase)) {
return PTR_ERR(port->membase); ret = PTR_ERR(port->membase);
goto err_erase_id;
}
/* values not from device tree */ /* values not from device tree */
port->dev = &pdev->dev; port->dev = &pdev->dev;
@ -285,7 +287,18 @@ static int liteuart_probe(struct platform_device *pdev)
port->line = dev_id; port->line = dev_id;
spin_lock_init(&port->lock); spin_lock_init(&port->lock);
return uart_add_one_port(&liteuart_driver, &uart->port); platform_set_drvdata(pdev, port);
ret = uart_add_one_port(&liteuart_driver, &uart->port);
if (ret)
goto err_erase_id;
return 0;
err_erase_id:
xa_erase(&liteuart_array, uart->id);
return ret;
} }
static int liteuart_remove(struct platform_device *pdev) static int liteuart_remove(struct platform_device *pdev)
@ -293,6 +306,7 @@ static int liteuart_remove(struct platform_device *pdev)
struct uart_port *port = platform_get_drvdata(pdev); struct uart_port *port = platform_get_drvdata(pdev);
struct liteuart_port *uart = to_liteuart_port(port); struct liteuart_port *uart = to_liteuart_port(port);
uart_remove_one_port(&liteuart_driver, port);
xa_erase(&liteuart_array, uart->id); xa_erase(&liteuart_array, uart->id);
return 0; return 0;

View File

@ -598,6 +598,9 @@ static void msm_start_rx_dma(struct msm_port *msm_port)
u32 val; u32 val;
int ret; int ret;
if (IS_ENABLED(CONFIG_CONSOLE_POLL))
return;
if (!dma->chan) if (!dma->chan)
return; return;

View File

@ -1506,7 +1506,7 @@ static struct tegra_uart_chip_data tegra20_uart_chip_data = {
.fifo_mode_enable_status = false, .fifo_mode_enable_status = false,
.uart_max_port = 5, .uart_max_port = 5,
.max_dma_burst_bytes = 4, .max_dma_burst_bytes = 4,
.error_tolerance_low_range = 0, .error_tolerance_low_range = -4,
.error_tolerance_high_range = 4, .error_tolerance_high_range = 4,
}; };
@ -1517,7 +1517,7 @@ static struct tegra_uart_chip_data tegra30_uart_chip_data = {
.fifo_mode_enable_status = false, .fifo_mode_enable_status = false,
.uart_max_port = 5, .uart_max_port = 5,
.max_dma_burst_bytes = 4, .max_dma_burst_bytes = 4,
.error_tolerance_low_range = 0, .error_tolerance_low_range = -4,
.error_tolerance_high_range = 4, .error_tolerance_high_range = 4,
}; };

View File

@ -1075,6 +1075,11 @@ uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
goto out; goto out;
if (!tty_io_error(tty)) { if (!tty_io_error(tty)) {
if (uport->rs485.flags & SER_RS485_ENABLED) {
set &= ~TIOCM_RTS;
clear &= ~TIOCM_RTS;
}
uart_update_mctrl(uport, set, clear); uart_update_mctrl(uport, set, clear);
ret = 0; ret = 0;
} }
@ -1549,6 +1554,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
{ {
struct uart_state *state = container_of(port, struct uart_state, port); struct uart_state *state = container_of(port, struct uart_state, port);
struct uart_port *uport = uart_port_check(state); struct uart_port *uport = uart_port_check(state);
char *buf;
/* /*
* At this point, we stop accepting input. To do this, we * At this point, we stop accepting input. To do this, we
@ -1570,8 +1576,18 @@ static void uart_tty_port_shutdown(struct tty_port *port)
*/ */
tty_port_set_suspended(port, 0); tty_port_set_suspended(port, 0);
uart_change_pm(state, UART_PM_STATE_OFF); /*
* Free the transmit buffer.
*/
spin_lock_irq(&uport->lock);
buf = state->xmit.buf;
state->xmit.buf = NULL;
spin_unlock_irq(&uport->lock);
if (buf)
free_page((unsigned long)buf);
uart_change_pm(state, UART_PM_STATE_OFF);
} }
static void uart_wait_until_sent(struct tty_struct *tty, int timeout) static void uart_wait_until_sent(struct tty_struct *tty, int timeout)

View File

@ -366,11 +366,17 @@ static void vgacon_init(struct vc_data *c, int init)
struct uni_pagedir *p; struct uni_pagedir *p;
/* /*
* We cannot be loaded as a module, therefore init is always 1, * We cannot be loaded as a module, therefore init will be 1
* but vgacon_init can be called more than once, and init will * if we are the default console, however if we are a fallback
* not be 1. * console, for example if fbcon has failed registration, then
* init will be 0, so we need to make sure our boot parameters
* have been copied to the console structure for vgacon_resize
* ultimately called by vc_resize. Any subsequent calls to
* vgacon_init init will have init set to 0 too.
*/ */
c->vc_can_do_color = vga_can_do_color; c->vc_can_do_color = vga_can_do_color;
c->vc_scan_lines = vga_scan_lines;
c->vc_font.height = c->vc_cell_height = vga_video_font_height;
/* set dimensions manually if init != 0 since vc_resize() will fail */ /* set dimensions manually if init != 0 since vc_resize() will fail */
if (init) { if (init) {
@ -379,8 +385,6 @@ static void vgacon_init(struct vc_data *c, int init)
} else } else
vc_resize(c, vga_video_num_columns, vga_video_num_lines); vc_resize(c, vga_video_num_columns, vga_video_num_lines);
c->vc_scan_lines = vga_scan_lines;
c->vc_font.height = c->vc_cell_height = vga_video_font_height;
c->vc_complement_mask = 0x7700; c->vc_complement_mask = 0x7700;
if (vga_512_chars) if (vga_512_chars)
c->vc_hi_font_mask = 0x0800; c->vc_hi_font_mask = 0x0800;