TTY/Serial driver fixes for 5.18-rc7

Here are some small tty n_gsm and serial driver fixes for 5.18-rc7 that
 resolve reported problems.  They include:
 	- n_gsm fixes for reported issues
 	- 8250_mtk driver fixes for some platforms
 	- fsl_lpuart driver fix for reported problem.
 	- digicolor driver fix for reported problem.
 
 All have been in linux-next for a while with no reported problems.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCYoEM8g8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ylkRgCePwdlqU8cJAePVKVEQVbBmqV2DQgAoL4aGeH7
 /4ZvKAc/3AmUOBU+46sa
 =my19
 -----END PGP SIGNATURE-----

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

Pull tty/serial driver fixes from Greg KH:
 "Here are some small tty n_gsm and serial driver fixes for 5.18-rc7
  that resolve reported problems. They include:

   - n_gsm fixes for reported issues

   - 8250_mtk driver fixes for some platforms

   - fsl_lpuart driver fix for reported problem.

   - digicolor driver fix for reported problem.

  All have been in linux-next for a while with no reported problems"

* tag 'tty-5.18-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
  fsl_lpuart: Don't enable interrupts too early
  tty: n_gsm: fix invalid gsmtty_write_room() result
  tty: n_gsm: fix mux activation issues in gsm_config()
  tty: n_gsm: fix buffer over-read in gsm_dlci_data()
  serial: 8250_mtk: Fix register address for XON/XOFF character
  serial: 8250_mtk: Make sure to select the right FEATURE_SEL
  serial: 8250_mtk: Fix UART_EFR register address
  tty/serial: digicolor: fix possible null-ptr-deref in digicolor_uart_probe()
This commit is contained in:
Linus Torvalds 2022-05-15 08:05:04 -07:00
commit 6811a466d2
4 changed files with 43 additions and 29 deletions

View file

@ -137,6 +137,7 @@ struct gsm_dlci {
int retries; int retries;
/* Uplink tty if active */ /* Uplink tty if active */
struct tty_port port; /* The tty bound to this DLCI if there is one */ struct tty_port port; /* The tty bound to this DLCI if there is one */
#define TX_SIZE 4096 /* Must be power of 2. */
struct kfifo fifo; /* Queue fifo for the DLCI */ struct kfifo fifo; /* Queue fifo for the DLCI */
int adaption; /* Adaption layer in use */ int adaption; /* Adaption layer in use */
int prev_adaption; int prev_adaption;
@ -1658,6 +1659,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen)
if (len == 0) if (len == 0)
return; return;
} }
len--;
slen++; slen++;
tty = tty_port_tty_get(port); tty = tty_port_tty_get(port);
if (tty) { if (tty) {
@ -1730,7 +1732,7 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
return NULL; return NULL;
spin_lock_init(&dlci->lock); spin_lock_init(&dlci->lock);
mutex_init(&dlci->mutex); mutex_init(&dlci->mutex);
if (kfifo_alloc(&dlci->fifo, 4096, GFP_KERNEL) < 0) { if (kfifo_alloc(&dlci->fifo, TX_SIZE, GFP_KERNEL) < 0) {
kfree(dlci); kfree(dlci);
return NULL; return NULL;
} }
@ -2351,6 +2353,7 @@ static void gsm_copy_config_values(struct gsm_mux *gsm,
static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c) static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
{ {
int ret = 0;
int need_close = 0; int need_close = 0;
int need_restart = 0; int need_restart = 0;
@ -2418,10 +2421,13 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
* FIXME: We need to separate activation/deactivation from adding * FIXME: We need to separate activation/deactivation from adding
* and removing from the mux array * and removing from the mux array
*/ */
if (need_restart) if (gsm->dead) {
gsm_activate_mux(gsm); ret = gsm_activate_mux(gsm);
if (gsm->initiator && need_close) if (ret)
gsm_dlci_begin_open(gsm->dlci[0]); return ret;
if (gsm->initiator)
gsm_dlci_begin_open(gsm->dlci[0]);
}
return 0; return 0;
} }
@ -2971,8 +2977,6 @@ static struct tty_ldisc_ops tty_ldisc_packet = {
* Virtual tty side * Virtual tty side
*/ */
#define TX_SIZE 512
/** /**
* gsm_modem_upd_via_data - send modem bits via convergence layer * gsm_modem_upd_via_data - send modem bits via convergence layer
* @dlci: channel * @dlci: channel
@ -3212,7 +3216,7 @@ static unsigned int gsmtty_write_room(struct tty_struct *tty)
struct gsm_dlci *dlci = tty->driver_data; struct gsm_dlci *dlci = tty->driver_data;
if (dlci->state == DLCI_CLOSED) if (dlci->state == DLCI_CLOSED)
return 0; return 0;
return TX_SIZE - kfifo_len(&dlci->fifo); return kfifo_avail(&dlci->fifo);
} }
static unsigned int gsmtty_chars_in_buffer(struct tty_struct *tty) static unsigned int gsmtty_chars_in_buffer(struct tty_struct *tty)

View file

@ -37,6 +37,7 @@
#define MTK_UART_IER_RTSI 0x40 /* Enable RTS Modem status interrupt */ #define MTK_UART_IER_RTSI 0x40 /* Enable RTS Modem status interrupt */
#define MTK_UART_IER_CTSI 0x80 /* Enable CTS Modem status interrupt */ #define MTK_UART_IER_CTSI 0x80 /* Enable CTS Modem status interrupt */
#define MTK_UART_EFR 38 /* I/O: Extended Features Register */
#define MTK_UART_EFR_EN 0x10 /* Enable enhancement feature */ #define MTK_UART_EFR_EN 0x10 /* Enable enhancement feature */
#define MTK_UART_EFR_RTS 0x40 /* Enable hardware rx flow control */ #define MTK_UART_EFR_RTS 0x40 /* Enable hardware rx flow control */
#define MTK_UART_EFR_CTS 0x80 /* Enable hardware tx flow control */ #define MTK_UART_EFR_CTS 0x80 /* Enable hardware tx flow control */
@ -53,6 +54,12 @@
#define MTK_UART_TX_TRIGGER 1 #define MTK_UART_TX_TRIGGER 1
#define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE #define MTK_UART_RX_TRIGGER MTK_UART_RX_SIZE
#define MTK_UART_FEATURE_SEL 39 /* Feature Selection register */
#define MTK_UART_FEAT_NEWRMAP BIT(0) /* Use new register map */
#define MTK_UART_XON1 40 /* I/O: Xon character 1 */
#define MTK_UART_XOFF1 42 /* I/O: Xoff character 1 */
#ifdef CONFIG_SERIAL_8250_DMA #ifdef CONFIG_SERIAL_8250_DMA
enum dma_rx_status { enum dma_rx_status {
DMA_RX_START = 0, DMA_RX_START = 0,
@ -169,7 +176,7 @@ static void mtk8250_dma_enable(struct uart_8250_port *up)
MTK_UART_DMA_EN_RX | MTK_UART_DMA_EN_TX); MTK_UART_DMA_EN_RX | MTK_UART_DMA_EN_TX);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_EFR, UART_EFR_ECB); serial_out(up, MTK_UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, lcr); serial_out(up, UART_LCR, lcr);
if (dmaengine_slave_config(dma->rxchan, &dma->rxconf) != 0) if (dmaengine_slave_config(dma->rxchan, &dma->rxconf) != 0)
@ -232,7 +239,7 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
int lcr = serial_in(up, UART_LCR); int lcr = serial_in(up, UART_LCR);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_EFR, UART_EFR_ECB); serial_out(up, MTK_UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, lcr); serial_out(up, UART_LCR, lcr);
lcr = serial_in(up, UART_LCR); lcr = serial_in(up, UART_LCR);
@ -241,7 +248,7 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
serial_out(up, MTK_UART_ESCAPE_DAT, MTK_UART_ESCAPE_CHAR); serial_out(up, MTK_UART_ESCAPE_DAT, MTK_UART_ESCAPE_CHAR);
serial_out(up, MTK_UART_ESCAPE_EN, 0x00); serial_out(up, MTK_UART_ESCAPE_EN, 0x00);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_EFR, serial_in(up, UART_EFR) & serial_out(up, MTK_UART_EFR, serial_in(up, MTK_UART_EFR) &
(~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK))); (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK)));
serial_out(up, UART_LCR, lcr); serial_out(up, UART_LCR, lcr);
mtk8250_disable_intrs(up, MTK_UART_IER_XOFFI | mtk8250_disable_intrs(up, MTK_UART_IER_XOFFI |
@ -255,8 +262,8 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
/*enable hw flow control*/ /*enable hw flow control*/
serial_out(up, UART_EFR, MTK_UART_EFR_HW_FC | serial_out(up, MTK_UART_EFR, MTK_UART_EFR_HW_FC |
(serial_in(up, UART_EFR) & (serial_in(up, MTK_UART_EFR) &
(~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK)))); (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK))));
serial_out(up, UART_LCR, lcr); serial_out(up, UART_LCR, lcr);
@ -270,12 +277,12 @@ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
/*enable sw flow control */ /*enable sw flow control */
serial_out(up, UART_EFR, MTK_UART_EFR_XON1_XOFF1 | serial_out(up, MTK_UART_EFR, MTK_UART_EFR_XON1_XOFF1 |
(serial_in(up, UART_EFR) & (serial_in(up, MTK_UART_EFR) &
(~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK)))); (~(MTK_UART_EFR_HW_FC | MTK_UART_EFR_SW_FC_MASK))));
serial_out(up, UART_XON1, START_CHAR(port->state->port.tty)); serial_out(up, MTK_UART_XON1, START_CHAR(port->state->port.tty));
serial_out(up, UART_XOFF1, STOP_CHAR(port->state->port.tty)); serial_out(up, MTK_UART_XOFF1, STOP_CHAR(port->state->port.tty));
serial_out(up, UART_LCR, lcr); serial_out(up, UART_LCR, lcr);
mtk8250_disable_intrs(up, MTK_UART_IER_CTSI|MTK_UART_IER_RTSI); mtk8250_disable_intrs(up, MTK_UART_IER_CTSI|MTK_UART_IER_RTSI);
mtk8250_enable_intrs(up, MTK_UART_IER_XOFFI); mtk8250_enable_intrs(up, MTK_UART_IER_XOFFI);
@ -568,6 +575,10 @@ static int mtk8250_probe(struct platform_device *pdev)
uart.dma = data->dma; uart.dma = data->dma;
#endif #endif
/* Set AP UART new register map */
writel(MTK_UART_FEAT_NEWRMAP, uart.port.membase +
(MTK_UART_FEATURE_SEL << uart.port.regshift));
/* Disable Rate Fix function */ /* Disable Rate Fix function */
writel(0x0, uart.port.membase + writel(0x0, uart.port.membase +
(MTK_UART_RATE_FIX << uart.port.regshift)); (MTK_UART_RATE_FIX << uart.port.regshift));

View file

@ -471,11 +471,10 @@ static int digicolor_uart_probe(struct platform_device *pdev)
if (IS_ERR(uart_clk)) if (IS_ERR(uart_clk))
return PTR_ERR(uart_clk); return PTR_ERR(uart_clk);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dp->port.membase = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
dp->port.mapbase = res->start;
dp->port.membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dp->port.membase)) if (IS_ERR(dp->port.membase))
return PTR_ERR(dp->port.membase); return PTR_ERR(dp->port.membase);
dp->port.mapbase = res->start;
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)

View file

@ -2664,6 +2664,7 @@ static int lpuart_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct lpuart_port *sport; struct lpuart_port *sport;
struct resource *res; struct resource *res;
irq_handler_t handler;
int ret; int ret;
sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL); sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
@ -2741,17 +2742,11 @@ static int lpuart_probe(struct platform_device *pdev)
if (lpuart_is_32(sport)) { if (lpuart_is_32(sport)) {
lpuart_reg.cons = LPUART32_CONSOLE; lpuart_reg.cons = LPUART32_CONSOLE;
ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart32_int, 0, handler = lpuart32_int;
DRIVER_NAME, sport);
} else { } else {
lpuart_reg.cons = LPUART_CONSOLE; lpuart_reg.cons = LPUART_CONSOLE;
ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart_int, 0, handler = lpuart_int;
DRIVER_NAME, sport);
} }
if (ret)
goto failed_irq_request;
ret = uart_add_one_port(&lpuart_reg, &sport->port); ret = uart_add_one_port(&lpuart_reg, &sport->port);
if (ret) if (ret)
goto failed_attach_port; goto failed_attach_port;
@ -2773,13 +2768,18 @@ static int lpuart_probe(struct platform_device *pdev)
sport->port.rs485_config(&sport->port, &sport->port.rs485); sport->port.rs485_config(&sport->port, &sport->port.rs485);
ret = devm_request_irq(&pdev->dev, sport->port.irq, handler, 0,
DRIVER_NAME, sport);
if (ret)
goto failed_irq_request;
return 0; return 0;
failed_irq_request:
failed_get_rs485: failed_get_rs485:
failed_reset: failed_reset:
uart_remove_one_port(&lpuart_reg, &sport->port); uart_remove_one_port(&lpuart_reg, &sport->port);
failed_attach_port: failed_attach_port:
failed_irq_request:
lpuart_disable_clks(sport); lpuart_disable_clks(sport);
failed_clock_enable: failed_clock_enable:
failed_out_of_range: failed_out_of_range: