Skip to content

Commit 2b2e71f

Browse files
mwallegregkh
authored andcommitted
tty: serial: fsl_lpuart: free IDs allocated by IDA
Since commit 3bc3206 ("serial: fsl_lpuart: Remove the alias node dependence") the port line number can also be allocated by IDA, but in case of an error the ID will no be removed again. More importantly, any ID will be freed in remove(), even if it wasn't allocated but instead fetched by of_alias_get_id(). If it was not allocated by IDA there will be a warning: WARN(1, "ida_free called for id=%d which is not allocated.\n", id); Move the ID allocation more to the end of the probe() so that we still can use plain return in the first error cases. Fixes: 3bc3206 ("serial: fsl_lpuart: Remove the alias node dependence") Signed-off-by: Michael Walle <[email protected]> Cc: stable <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 0e28ed6 commit 2b2e71f

File tree

1 file changed

+24
-15
lines changed

1 file changed

+24
-15
lines changed

drivers/tty/serial/fsl_lpuart.c

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ struct lpuart_port {
264264
int rx_dma_rng_buf_len;
265265
unsigned int dma_tx_nents;
266266
wait_queue_head_t dma_wait;
267+
bool id_allocated;
267268
};
268269

269270
struct lpuart_soc_data {
@@ -2422,19 +2423,6 @@ static int lpuart_probe(struct platform_device *pdev)
24222423
if (!sport)
24232424
return -ENOMEM;
24242425

2425-
ret = of_alias_get_id(np, "serial");
2426-
if (ret < 0) {
2427-
ret = ida_simple_get(&fsl_lpuart_ida, 0, UART_NR, GFP_KERNEL);
2428-
if (ret < 0) {
2429-
dev_err(&pdev->dev, "port line is full, add device failed\n");
2430-
return ret;
2431-
}
2432-
}
2433-
if (ret >= ARRAY_SIZE(lpuart_ports)) {
2434-
dev_err(&pdev->dev, "serial%d out of range\n", ret);
2435-
return -EINVAL;
2436-
}
2437-
sport->port.line = ret;
24382426
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
24392427
sport->port.membase = devm_ioremap_resource(&pdev->dev, res);
24402428
if (IS_ERR(sport->port.membase))
@@ -2479,9 +2467,25 @@ static int lpuart_probe(struct platform_device *pdev)
24792467
}
24802468
}
24812469

2470+
ret = of_alias_get_id(np, "serial");
2471+
if (ret < 0) {
2472+
ret = ida_simple_get(&fsl_lpuart_ida, 0, UART_NR, GFP_KERNEL);
2473+
if (ret < 0) {
2474+
dev_err(&pdev->dev, "port line is full, add device failed\n");
2475+
return ret;
2476+
}
2477+
sport->id_allocated = true;
2478+
}
2479+
if (ret >= ARRAY_SIZE(lpuart_ports)) {
2480+
dev_err(&pdev->dev, "serial%d out of range\n", ret);
2481+
ret = -EINVAL;
2482+
goto failed_out_of_range;
2483+
}
2484+
sport->port.line = ret;
2485+
24822486
ret = lpuart_enable_clks(sport);
24832487
if (ret)
2484-
return ret;
2488+
goto failed_clock_enable;
24852489
sport->port.uartclk = lpuart_get_baud_clk_rate(sport);
24862490

24872491
lpuart_ports[sport->port.line] = sport;
@@ -2531,6 +2535,10 @@ static int lpuart_probe(struct platform_device *pdev)
25312535
failed_attach_port:
25322536
failed_irq_request:
25332537
lpuart_disable_clks(sport);
2538+
failed_clock_enable:
2539+
failed_out_of_range:
2540+
if (sport->id_allocated)
2541+
ida_simple_remove(&fsl_lpuart_ida, sport->port.line);
25342542
return ret;
25352543
}
25362544

@@ -2540,7 +2548,8 @@ static int lpuart_remove(struct platform_device *pdev)
25402548

25412549
uart_remove_one_port(&lpuart_reg, &sport->port);
25422550

2543-
ida_simple_remove(&fsl_lpuart_ida, sport->port.line);
2551+
if (sport->id_allocated)
2552+
ida_simple_remove(&fsl_lpuart_ida, sport->port.line);
25442553

25452554
lpuart_disable_clks(sport);
25462555

0 commit comments

Comments
 (0)