Revert "serial: uartps: Change uart ID port allocation"
This reverts commit ae1cca3fa3
.
With setting up NR_PORTS to 16 to be able to use serial2 and higher
aliases and don't loose functionality which was intended by these changes.
As Johan says, this driver needs a lot more work and these changes are
only going in the wrong direction:
https://lkml.kernel.org/r/20190523091839.GC568@localhost
Reported-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Cc: stable <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/a94931b65ce0089f76fb1fe6b446a08731bff754.1585905873.git.michal.simek@xilinx.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
91c9dfa25c
Коммит
72d6819728
|
@ -27,6 +27,7 @@
|
||||||
#define CDNS_UART_TTY_NAME "ttyPS"
|
#define CDNS_UART_TTY_NAME "ttyPS"
|
||||||
#define CDNS_UART_NAME "xuartps"
|
#define CDNS_UART_NAME "xuartps"
|
||||||
#define CDNS_UART_MAJOR 0 /* use dynamic node allocation */
|
#define CDNS_UART_MAJOR 0 /* use dynamic node allocation */
|
||||||
|
#define CDNS_UART_NR_PORTS 16
|
||||||
#define CDNS_UART_FIFO_SIZE 64 /* FIFO size */
|
#define CDNS_UART_FIFO_SIZE 64 /* FIFO size */
|
||||||
#define CDNS_UART_REGISTER_SPACE 0x1000
|
#define CDNS_UART_REGISTER_SPACE 0x1000
|
||||||
#define TX_TIMEOUT 500000
|
#define TX_TIMEOUT 500000
|
||||||
|
@ -1403,90 +1404,6 @@ static const struct of_device_id cdns_uart_of_match[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, cdns_uart_of_match);
|
MODULE_DEVICE_TABLE(of, cdns_uart_of_match);
|
||||||
|
|
||||||
/*
|
|
||||||
* Maximum number of instances without alias IDs but if there is alias
|
|
||||||
* which target "< MAX_UART_INSTANCES" range this ID can't be used.
|
|
||||||
*/
|
|
||||||
#define MAX_UART_INSTANCES 32
|
|
||||||
|
|
||||||
/* Stores static aliases list */
|
|
||||||
static DECLARE_BITMAP(alias_bitmap, MAX_UART_INSTANCES);
|
|
||||||
static int alias_bitmap_initialized;
|
|
||||||
|
|
||||||
/* Stores actual bitmap of allocated IDs with alias IDs together */
|
|
||||||
static DECLARE_BITMAP(bitmap, MAX_UART_INSTANCES);
|
|
||||||
/* Protect bitmap operations to have unique IDs */
|
|
||||||
static DEFINE_MUTEX(bitmap_lock);
|
|
||||||
|
|
||||||
static int cdns_get_id(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
int id, ret;
|
|
||||||
|
|
||||||
mutex_lock(&bitmap_lock);
|
|
||||||
|
|
||||||
/* Alias list is stable that's why get alias bitmap only once */
|
|
||||||
if (!alias_bitmap_initialized) {
|
|
||||||
ret = of_alias_get_alias_list(cdns_uart_of_match, "serial",
|
|
||||||
alias_bitmap, MAX_UART_INSTANCES);
|
|
||||||
if (ret && ret != -EOVERFLOW) {
|
|
||||||
mutex_unlock(&bitmap_lock);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
alias_bitmap_initialized++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure that alias ID is not taken by instance without alias */
|
|
||||||
bitmap_or(bitmap, bitmap, alias_bitmap, MAX_UART_INSTANCES);
|
|
||||||
|
|
||||||
dev_dbg(&pdev->dev, "Alias bitmap: %*pb\n",
|
|
||||||
MAX_UART_INSTANCES, bitmap);
|
|
||||||
|
|
||||||
/* Look for a serialN alias */
|
|
||||||
id = of_alias_get_id(pdev->dev.of_node, "serial");
|
|
||||||
if (id < 0) {
|
|
||||||
dev_warn(&pdev->dev,
|
|
||||||
"No serial alias passed. Using the first free id\n");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Start with id 0 and check if there is no serial0 alias
|
|
||||||
* which points to device which is compatible with this driver.
|
|
||||||
* If alias exists then try next free position.
|
|
||||||
*/
|
|
||||||
id = 0;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
dev_info(&pdev->dev, "Checking id %d\n", id);
|
|
||||||
id = find_next_zero_bit(bitmap, MAX_UART_INSTANCES, id);
|
|
||||||
|
|
||||||
/* No free empty instance */
|
|
||||||
if (id == MAX_UART_INSTANCES) {
|
|
||||||
dev_err(&pdev->dev, "No free ID\n");
|
|
||||||
mutex_unlock(&bitmap_lock);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_dbg(&pdev->dev, "The empty id is %d\n", id);
|
|
||||||
/* Check if ID is empty */
|
|
||||||
if (!test_and_set_bit(id, bitmap)) {
|
|
||||||
/* Break the loop if bit is taken */
|
|
||||||
dev_dbg(&pdev->dev,
|
|
||||||
"Selected ID %d allocation passed\n",
|
|
||||||
id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dev_dbg(&pdev->dev,
|
|
||||||
"Selected ID %d allocation failed\n", id);
|
|
||||||
/* if taking bit fails then try next one */
|
|
||||||
id++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&bitmap_lock);
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cdns_uart_probe - Platform driver probe
|
* cdns_uart_probe - Platform driver probe
|
||||||
* @pdev: Pointer to the platform device structure
|
* @pdev: Pointer to the platform device structure
|
||||||
|
@ -1520,17 +1437,21 @@ static int cdns_uart_probe(struct platform_device *pdev)
|
||||||
if (!cdns_uart_uart_driver)
|
if (!cdns_uart_uart_driver)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
cdns_uart_data->id = cdns_get_id(pdev);
|
/* Look for a serialN alias */
|
||||||
|
cdns_uart_data->id = of_alias_get_id(pdev->dev.of_node, "serial");
|
||||||
if (cdns_uart_data->id < 0)
|
if (cdns_uart_data->id < 0)
|
||||||
return cdns_uart_data->id;
|
cdns_uart_data->id = 0;
|
||||||
|
|
||||||
|
if (cdns_uart_data->id >= CDNS_UART_NR_PORTS) {
|
||||||
|
dev_err(&pdev->dev, "Cannot get uart_port structure\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
/* There is a need to use unique driver name */
|
/* There is a need to use unique driver name */
|
||||||
driver_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s%d",
|
driver_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s%d",
|
||||||
CDNS_UART_NAME, cdns_uart_data->id);
|
CDNS_UART_NAME, cdns_uart_data->id);
|
||||||
if (!driver_name) {
|
if (!driver_name)
|
||||||
rc = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto err_out_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
cdns_uart_uart_driver->owner = THIS_MODULE;
|
cdns_uart_uart_driver->owner = THIS_MODULE;
|
||||||
cdns_uart_uart_driver->driver_name = driver_name;
|
cdns_uart_uart_driver->driver_name = driver_name;
|
||||||
|
@ -1559,7 +1480,7 @@ static int cdns_uart_probe(struct platform_device *pdev)
|
||||||
rc = uart_register_driver(cdns_uart_uart_driver);
|
rc = uart_register_driver(cdns_uart_uart_driver);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
dev_err(&pdev->dev, "Failed to register driver\n");
|
dev_err(&pdev->dev, "Failed to register driver\n");
|
||||||
goto err_out_id;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdns_uart_data->cdns_uart_driver = cdns_uart_uart_driver;
|
cdns_uart_data->cdns_uart_driver = cdns_uart_uart_driver;
|
||||||
|
@ -1710,10 +1631,7 @@ err_out_clk_dis_pclk:
|
||||||
clk_disable_unprepare(cdns_uart_data->pclk);
|
clk_disable_unprepare(cdns_uart_data->pclk);
|
||||||
err_out_unregister_driver:
|
err_out_unregister_driver:
|
||||||
uart_unregister_driver(cdns_uart_data->cdns_uart_driver);
|
uart_unregister_driver(cdns_uart_data->cdns_uart_driver);
|
||||||
err_out_id:
|
|
||||||
mutex_lock(&bitmap_lock);
|
|
||||||
clear_bit(cdns_uart_data->id, bitmap);
|
|
||||||
mutex_unlock(&bitmap_lock);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1736,9 +1654,6 @@ static int cdns_uart_remove(struct platform_device *pdev)
|
||||||
#endif
|
#endif
|
||||||
rc = uart_remove_one_port(cdns_uart_data->cdns_uart_driver, port);
|
rc = uart_remove_one_port(cdns_uart_data->cdns_uart_driver, port);
|
||||||
port->mapbase = 0;
|
port->mapbase = 0;
|
||||||
mutex_lock(&bitmap_lock);
|
|
||||||
clear_bit(cdns_uart_data->id, bitmap);
|
|
||||||
mutex_unlock(&bitmap_lock);
|
|
||||||
clk_disable_unprepare(cdns_uart_data->uartclk);
|
clk_disable_unprepare(cdns_uart_data->uartclk);
|
||||||
clk_disable_unprepare(cdns_uart_data->pclk);
|
clk_disable_unprepare(cdns_uart_data->pclk);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче