History

tty: serial: fsl_lpuart: free IDs allocated by IDA

Since commit 3bc3206e1c0f ("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.

Michael Walle committed 6 years ago

Commit 2b2e71f1 parent 0e28ed61 file · +24 −15Browse files

Unified · Split

drivers/tty/serial/fsl_lpuart.c+24−15
@@ -264,6 +264,7 @@ struct lpuart_port { · 263 unmodified lines
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) · 2152 unmodified lines
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) · 38 unmodified lines
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) · 43 unmodified lines
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) · 3 unmodified lines
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

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t