Skip to content

Commit ae1cca3

Browse files
Michal Simekgregkh
authored andcommitted
serial: uartps: Change uart ID port allocation
For IPs which have alias algorightm all the time using that alias and minor number. It means serial20 alias ends up as ttyPS20. If alias is not setup for probed IP instance the first unused position is used but that needs to be checked if it is really empty because another instance doesn't need to be probed at that time. of_alias_get_alias_list() fills alias bitmap which exactly shows which ID is free. If alias pointing to different not compatible IP, it is free to use. cdns_get_id() call is placed below structure allocation to simplify error path. Signed-off-by: Michal Simek <michal.simek@xilinx.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent b1078c3 commit ae1cca3

File tree

1 file changed

+96
-13
lines changed

1 file changed

+96
-13
lines changed

drivers/tty/serial/xilinx_uartps.c

Lines changed: 96 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#define CDNS_UART_TTY_NAME "ttyPS"
3131
#define CDNS_UART_NAME "xuartps"
3232
#define CDNS_UART_MAJOR 0 /* use dynamic node allocation */
33-
#define CDNS_UART_NR_PORTS 2
3433
#define CDNS_UART_FIFO_SIZE 64 /* FIFO size */
3534
#define CDNS_UART_REGISTER_SPACE 0x1000
3635

@@ -1370,6 +1369,88 @@ static const struct of_device_id cdns_uart_of_match[] = {
13701369
};
13711370
MODULE_DEVICE_TABLE(of, cdns_uart_of_match);
13721371

1372+
/*
1373+
* Maximum number of instances without alias IDs but if there is alias
1374+
* which target "< MAX_UART_INSTANCES" range this ID can't be used.
1375+
*/
1376+
#define MAX_UART_INSTANCES 32
1377+
1378+
/* Stores static aliases list */
1379+
static DECLARE_BITMAP(alias_bitmap, MAX_UART_INSTANCES);
1380+
static int alias_bitmap_initialized;
1381+
1382+
/* Stores actual bitmap of allocated IDs with alias IDs together */
1383+
static DECLARE_BITMAP(bitmap, MAX_UART_INSTANCES);
1384+
/* Protect bitmap operations to have unique IDs */
1385+
static DEFINE_MUTEX(bitmap_lock);
1386+
1387+
static int cdns_get_id(struct platform_device *pdev)
1388+
{
1389+
int id, ret;
1390+
1391+
mutex_lock(&bitmap_lock);
1392+
1393+
/* Alias list is stable that's why get alias bitmap only once */
1394+
if (!alias_bitmap_initialized) {
1395+
ret = of_alias_get_alias_list(cdns_uart_of_match, "serial",
1396+
alias_bitmap, MAX_UART_INSTANCES);
1397+
if (ret)
1398+
return ret;
1399+
1400+
alias_bitmap_initialized++;
1401+
}
1402+
1403+
/* Make sure that alias ID is not taken by instance without alias */
1404+
bitmap_or(bitmap, bitmap, alias_bitmap, MAX_UART_INSTANCES);
1405+
1406+
dev_dbg(&pdev->dev, "Alias bitmap: %*pb\n",
1407+
MAX_UART_INSTANCES, bitmap);
1408+
1409+
/* Look for a serialN alias */
1410+
id = of_alias_get_id(pdev->dev.of_node, "serial");
1411+
if (id < 0) {
1412+
dev_warn(&pdev->dev,
1413+
"No serial alias passed. Using the first free id\n");
1414+
1415+
/*
1416+
* Start with id 0 and check if there is no serial0 alias
1417+
* which points to device which is compatible with this driver.
1418+
* If alias exists then try next free position.
1419+
*/
1420+
id = 0;
1421+
1422+
for (;;) {
1423+
dev_info(&pdev->dev, "Checking id %d\n", id);
1424+
id = find_next_zero_bit(bitmap, MAX_UART_INSTANCES, id);
1425+
1426+
/* No free empty instance */
1427+
if (id == MAX_UART_INSTANCES) {
1428+
dev_err(&pdev->dev, "No free ID\n");
1429+
mutex_unlock(&bitmap_lock);
1430+
return -EINVAL;
1431+
}
1432+
1433+
dev_dbg(&pdev->dev, "The empty id is %d\n", id);
1434+
/* Check if ID is empty */
1435+
if (!test_and_set_bit(id, bitmap)) {
1436+
/* Break the loop if bit is taken */
1437+
dev_dbg(&pdev->dev,
1438+
"Selected ID %d allocation passed\n",
1439+
id);
1440+
break;
1441+
}
1442+
dev_dbg(&pdev->dev,
1443+
"Selected ID %d allocation failed\n", id);
1444+
/* if taking bit fails then try next one */
1445+
id++;
1446+
}
1447+
}
1448+
1449+
mutex_unlock(&bitmap_lock);
1450+
1451+
return id;
1452+
}
1453+
13731454
/**
13741455
* cdns_uart_probe - Platform driver probe
13751456
* @pdev: Pointer to the platform device structure
@@ -1403,21 +1484,17 @@ static int cdns_uart_probe(struct platform_device *pdev)
14031484
if (!cdns_uart_uart_driver)
14041485
return -ENOMEM;
14051486

1406-
/* Look for a serialN alias */
1407-
cdns_uart_data->id = of_alias_get_id(pdev->dev.of_node, "serial");
1487+
cdns_uart_data->id = cdns_get_id(pdev);
14081488
if (cdns_uart_data->id < 0)
1409-
cdns_uart_data->id = 0;
1410-
1411-
if (cdns_uart_data->id >= CDNS_UART_NR_PORTS) {
1412-
dev_err(&pdev->dev, "Cannot get uart_port structure\n");
1413-
return -ENODEV;
1414-
}
1489+
return cdns_uart_data->id;
14151490

14161491
/* There is a need to use unique driver name */
14171492
driver_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s%d",
14181493
CDNS_UART_NAME, cdns_uart_data->id);
1419-
if (!driver_name)
1420-
return -ENOMEM;
1494+
if (!driver_name) {
1495+
rc = -ENOMEM;
1496+
goto err_out_id;
1497+
}
14211498

14221499
cdns_uart_uart_driver->owner = THIS_MODULE;
14231500
cdns_uart_uart_driver->driver_name = driver_name;
@@ -1446,7 +1523,7 @@ static int cdns_uart_probe(struct platform_device *pdev)
14461523
rc = uart_register_driver(cdns_uart_uart_driver);
14471524
if (rc < 0) {
14481525
dev_err(&pdev->dev, "Failed to register driver\n");
1449-
return rc;
1526+
goto err_out_id;
14501527
}
14511528

14521529
cdns_uart_data->cdns_uart_driver = cdns_uart_uart_driver;
@@ -1587,7 +1664,10 @@ static int cdns_uart_probe(struct platform_device *pdev)
15871664
clk_disable_unprepare(cdns_uart_data->pclk);
15881665
err_out_unregister_driver:
15891666
uart_unregister_driver(cdns_uart_data->cdns_uart_driver);
1590-
1667+
err_out_id:
1668+
mutex_lock(&bitmap_lock);
1669+
clear_bit(cdns_uart_data->id, bitmap);
1670+
mutex_unlock(&bitmap_lock);
15911671
return rc;
15921672
}
15931673

@@ -1610,6 +1690,9 @@ static int cdns_uart_remove(struct platform_device *pdev)
16101690
#endif
16111691
rc = uart_remove_one_port(cdns_uart_data->cdns_uart_driver, port);
16121692
port->mapbase = 0;
1693+
mutex_lock(&bitmap_lock);
1694+
clear_bit(cdns_uart_data->id, bitmap);
1695+
mutex_unlock(&bitmap_lock);
16131696
clk_disable_unprepare(cdns_uart_data->uartclk);
16141697
clk_disable_unprepare(cdns_uart_data->pclk);
16151698
pm_runtime_disable(&pdev->dev);

0 commit comments

Comments
 (0)