Hi Shenwei, > > Subject: [PATCH] tty: serial: fsl_lpuart: fix potential bug when using > > both of_alias_get_id and ida_simple_get > > > > Now fsl_lpuart driver use both of_alias_get_id() and ida_simple_get() > > in .probe(), which has the potential bug. For example, when remove the > > lpuart7 alias in dts, of_alias_get_id() will return error, then call > > ida_simple_get() to allocate the id 0 for lpuart7, this may confilct > > with the > > lpuart4 which has alias 0. > > The behavior of ida_simple_get() is to allocate an unused alias number. Do > you see any conflict when you test? > Yes, I have verified this on imx8ulp, I print the port.line value for each uart port. When I remove the lpuart7 alias, the lpuart7 will get the id 0, same as lpuart4, which caused the lpuart7 probe fail. ida_simple_get() cannot figure out which id has been used in the uart driver. [ 0.894549] port.line = 0 --> lpuart4 [ 0.908148] port.line = 1 --> lpuart5 [ 0.939844] port.line = 2 --> lpuart6 [ 0.953608] port.line = 0 --> lpuart7 --- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi @@ -25,7 +25,6 @@ serial0 = &lpuart4; serial1 = &lpuart5; serial2 = &lpuart6; - serial3 = &lpuart7; }; Best regards Sherry > Regards, > Shenwei > > > > > aliases { > > ... > > serial0 = &lpuart4; > > serial1 = &lpuart5; > > serial2 = &lpuart6; > > serial3 = &lpuart7; > > } > > > > So remove the ida_simple_get() in .probe(), return an error directly > > when calling > > of_alias_get_id() fails, which is consistent with other uart drivers behavior. > > > > Fixes: 3bc3206e1c0f ("serial: fsl_lpuart: Remove the alias node > > dependence") > > Signed-off-by: Sherry Sun <sherry.sun@xxxxxxx> > > --- > > drivers/tty/serial/fsl_lpuart.c | 24 ++++-------------------- > > 1 file changed, 4 insertions(+), 20 deletions(-) > > > > diff --git a/drivers/tty/serial/fsl_lpuart.c > > b/drivers/tty/serial/fsl_lpuart.c index 452a015825ba..40465d23d7ad > > 100644 > > --- a/drivers/tty/serial/fsl_lpuart.c > > +++ b/drivers/tty/serial/fsl_lpuart.c > > @@ -239,8 +239,6 @@ > > /* IMX lpuart has four extra unused regs located at the beginning */ > > #define IMX_REG_OFF 0x10 > > > > -static DEFINE_IDA(fsl_lpuart_ida); > > - > > enum lpuart_type { > > VF610_LPUART, > > LS1021A_LPUART, > > @@ -276,7 +274,6 @@ struct lpuart_port { > > int rx_dma_rng_buf_len; > > unsigned int dma_tx_nents; > > wait_queue_head_t dma_wait; > > - bool id_allocated; > > }; > > > > struct lpuart_soc_data { > > @@ -2716,23 +2713,18 @@ static int lpuart_probe(struct platform_device > > *pdev) > > > > ret = of_alias_get_id(np, "serial"); > > if (ret < 0) { > > - ret = ida_simple_get(&fsl_lpuart_ida, 0, UART_NR, > > GFP_KERNEL); > > - if (ret < 0) { > > - dev_err(&pdev->dev, "port line is full, add device > > failed\n"); > > - return ret; > > - } > > - sport->id_allocated = true; > > + dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret); > > + return ret; > > } > > if (ret >= ARRAY_SIZE(lpuart_ports)) { > > dev_err(&pdev->dev, "serial%d out of range\n", ret); > > - ret = -EINVAL; > > - goto failed_out_of_range; > > + return -EINVAL; > > } > > sport->port.line = ret; > > > > ret = lpuart_enable_clks(sport); > > if (ret) > > - goto failed_clock_enable; > > + return ret; > > sport->port.uartclk = lpuart_get_baud_clk_rate(sport); > > > > lpuart_ports[sport->port.line] = sport; @@ -2781,10 +2773,6 @@ > > static int lpuart_probe(struct platform_device *pdev) > > failed_attach_port: > > failed_irq_request: > > lpuart_disable_clks(sport); > > -failed_clock_enable: > > -failed_out_of_range: > > - if (sport->id_allocated) > > - ida_simple_remove(&fsl_lpuart_ida, sport->port.line); > > return ret; > > } > > > > @@ -2794,9 +2782,6 @@ static int lpuart_remove(struct platform_device > > *pdev) > > > > uart_remove_one_port(&lpuart_reg, &sport->port); > > > > - if (sport->id_allocated) > > - ida_simple_remove(&fsl_lpuart_ida, sport->port.line); > > - > > lpuart_disable_clks(sport); > > > > if (sport->dma_tx_chan) > > @@ -2926,7 +2911,6 @@ static int __init lpuart_serial_init(void) > > > > static void __exit lpuart_serial_exit(void) { > > - ida_destroy(&fsl_lpuart_ida); > > platform_driver_unregister(&lpuart_driver); > > uart_unregister_driver(&lpuart_reg); > > } > > -- > > 2.17.1