From: Shubhrajyoti Datta <[email protected]>
Currently the number of uarts are configured through a Kconfig
option Make it dynamic.
While at it adapt to the runtime framework.
It is based a similar series on the uartps from Michal
Shubhrajyoti Datta (9):
serial-uartlite: Move the uart register
serial-uartlite: Add get serial id if not provided
serial-uartlite: Do not use static struct uart_driver out of probe()
serial-uartlite: Add runtime support
serial-uartlite: Fix the unbind path
serial-uartlite: Change logic how console_port is setup
serial-uartlite: Use allocated structure instead of static ones
serial-uartlite: Remove ULITE_NR_PORTS macro
serial-uartlite: Remove SERIAL_UARTLITE_NR_UARTS
drivers/tty/serial/Kconfig | 9 --
drivers/tty/serial/uartlite.c | 325 +++++++++++++++++++++++++++++++-----------
2 files changed, 243 insertions(+), 91 deletions(-)
--
2.1.1
From: Shubhrajyoti Datta <[email protected]>
Move the uart register. This fixes the error path where the
clock disable is missed out.
Signed-off-by: Shubhrajyoti Datta <[email protected]>
---
drivers/tty/serial/uartlite.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index f0344ad..77bc9d0 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -763,6 +763,15 @@ static int ulite_probe(struct platform_device *pdev)
if (prop)
id = be32_to_cpup(prop);
#endif
+ if (!ulite_uart_driver.state) {
+ dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n");
+ ret = uart_register_driver(&ulite_uart_driver);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register driver\n");
+ return ret;
+ }
+ }
+
pdata = devm_kzalloc(&pdev->dev, sizeof(struct uartlite_data),
GFP_KERNEL);
if (!pdata)
@@ -794,15 +803,6 @@ static int ulite_probe(struct platform_device *pdev)
return ret;
}
- if (!ulite_uart_driver.state) {
- dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n");
- ret = uart_register_driver(&ulite_uart_driver);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to register driver\n");
- return ret;
- }
- }
-
ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata);
clk_disable(pdata->clk);
--
2.1.1
From: Shubhrajyoti Datta <[email protected]>
ulite_uart_suspend()/resume() and remove() are using static reference
to struct uart_driver. Assign this referece to private data structure
as preparation step for dynamic struct uart_driver allocation.
Signed-off-by: Shubhrajyoti Datta <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
drivers/tty/serial/uartlite.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 441a216..64c7248 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -63,6 +63,7 @@ static struct uart_port *console_port;
struct uartlite_data {
const struct uartlite_reg_ops *reg_ops;
struct clk *clk;
+ struct uart_driver *ulite_uart_driver;
};
struct uartlite_reg_ops {
@@ -691,10 +692,11 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq,
static int ulite_release(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
+ struct uartlite_data *pdata = port->private_data;
int rc = 0;
if (port) {
- rc = uart_remove_one_port(&ulite_uart_driver, port);
+ rc = uart_remove_one_port(pdata->ulite_uart_driver, port);
dev_set_drvdata(dev, NULL);
port->mapbase = 0;
}
@@ -711,9 +713,10 @@ static int ulite_release(struct device *dev)
static int __maybe_unused ulite_suspend(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
+ struct uartlite_data *pdata = port->private_data;
if (port)
- uart_suspend_port(&ulite_uart_driver, port);
+ uart_suspend_port(pdata->ulite_uart_driver, port);
return 0;
}
@@ -727,9 +730,10 @@ static int __maybe_unused ulite_suspend(struct device *dev)
static int __maybe_unused ulite_resume(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
+ struct uartlite_data *pdata = port->private_data;
if (port)
- uart_resume_port(&ulite_uart_driver, port);
+ uart_resume_port(pdata->ulite_uart_driver, port);
return 0;
}
@@ -804,6 +808,7 @@ static int ulite_probe(struct platform_device *pdev)
pdata->clk = NULL;
}
+ pdata->ulite_uart_driver = &ulite_uart_driver;
ret = clk_prepare_enable(pdata->clk);
if (ret) {
dev_err(&pdev->dev, "Failed to prepare clock\n");
--
2.1.1
From: Shubhrajyoti Datta <[email protected]>
Currently the clocks are not enabled at probe but when the port is used.
Remove the unconditional disable at remove.
Fixes the below
[ 77.660196] ------------[ cut here ]------------
[ 77.664749] WARNING: CPU: 0 PID: 1992 at drivers/clk/clk.c:622
clk_core_disable+0x78/0x80
[ 77.672892] Modules linked in:
[ 77.675930] CPU: 0 PID: 1992 Comm: sh Not tainted 4.14.0 #23
[ 77.681570] Hardware name: xlnx,zynqmp (DT)
[ 77.685736] task: ffffffc879e2e580 task.stack: ffffff800be30000
[ 77.691641] PC is at clk_core_disable+0x78/0x80
Signed-off-by: Shubhrajyoti Datta <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
drivers/tty/serial/uartlite.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 58296eb..4a7989d 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -857,7 +857,7 @@ static int ulite_remove(struct platform_device *pdev)
struct uartlite_data *pdata = port->private_data;
int rc;
- clk_disable_unprepare(pdata->clk);
+ clk_unprepare(pdata->clk);
rc = ulite_release(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
--
2.1.1
From: Shubhrajyoti Datta <[email protected]>
Change logic how console_port is setup by using CON_ENABLED flag
instead of index. There will be unique uart_console
structure that's why code can't use id for console_port
assignment.
Signed-off-by: Shubhrajyoti Datta <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
drivers/tty/serial/uartlite.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 4a7989d..9c99a1d9 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -665,7 +665,7 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq,
* If register_console() don't assign value, then console_port pointer
* is cleanup.
*/
- if (ulite_uart_driver.cons->index == -1)
+ if (!console_port)
console_port = port;
#endif
@@ -680,7 +680,8 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq,
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
/* This is not port which is used for console that's why clean it up */
- if (ulite_uart_driver.cons->index == -1)
+ if (console_port == port &&
+ !(ulite_uart_driver->cons->flags & CON_ENABLED))
console_port = NULL;
#endif
@@ -859,6 +860,11 @@ static int ulite_remove(struct platform_device *pdev)
clk_unprepare(pdata->clk);
rc = ulite_release(&pdev->dev);
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+ if (console_port == port)
+ console_port = NULL;
+#endif
+
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
--
2.1.1
From: Shubhrajyoti Datta <[email protected]>
Add runtime support
Signed-off-by: Shubhrajyoti Datta <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
drivers/tty/serial/uartlite.c | 52 +++++++++++++++++++++++++++++++++++--------
1 file changed, 43 insertions(+), 9 deletions(-)
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 64c7248..58296eb 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -22,6 +22,7 @@
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/clk.h>
+#include <linux/pm_runtime.h>
#define ULITE_NAME "ttyUL"
#define ULITE_MAJOR 204
@@ -54,6 +55,7 @@
#define ULITE_CONTROL_RST_TX 0x01
#define ULITE_CONTROL_RST_RX 0x02
#define ULITE_CONTROL_IE 0x10
+#define UART_AUTOSUSPEND_TIMEOUT 3000
/* Static pointer to console port */
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
@@ -391,12 +393,12 @@ static int ulite_verify_port(struct uart_port *port, struct serial_struct *ser)
static void ulite_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
- struct uartlite_data *pdata = port->private_data;
-
- if (!state)
- clk_enable(pdata->clk);
- else
- clk_disable(pdata->clk);
+ if (!state) {
+ pm_runtime_get_sync(port->dev);
+ } else {
+ pm_runtime_mark_last_busy(port->dev);
+ pm_runtime_put_autosuspend(port->dev);
+ }
}
#ifdef CONFIG_CONSOLE_POLL
@@ -738,11 +740,32 @@ static int __maybe_unused ulite_resume(struct device *dev)
return 0;
}
+static int __maybe_unused ulite_runtime_suspend(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ struct uartlite_data *pdata = port->private_data;
+
+ clk_disable(pdata->clk);
+ return 0;
+};
+
+static int __maybe_unused ulite_runtime_resume(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+ struct uartlite_data *pdata = port->private_data;
+
+ clk_enable(pdata->clk);
+ return 0;
+}
/* ---------------------------------------------------------------------
* Platform bus binding
*/
-static SIMPLE_DEV_PM_OPS(ulite_pm_ops, ulite_suspend, ulite_resume);
+static const struct dev_pm_ops ulite_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(ulite_suspend, ulite_resume)
+ SET_RUNTIME_PM_OPS(ulite_runtime_suspend,
+ ulite_runtime_resume, NULL)
+};
#if defined(CONFIG_OF)
/* Match table for of_platform binding */
@@ -815,9 +838,15 @@ static int ulite_probe(struct platform_device *pdev)
return ret;
}
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata);
- clk_disable(pdata->clk);
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
return ret;
}
@@ -826,9 +855,14 @@ static int ulite_remove(struct platform_device *pdev)
{
struct uart_port *port = dev_get_drvdata(&pdev->dev);
struct uartlite_data *pdata = port->private_data;
+ int rc;
clk_disable_unprepare(pdata->clk);
- return ulite_release(&pdev->dev);
+ rc = ulite_release(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+ return rc;
}
/* work with hotplug and coldplug */
--
2.1.1
From: Shubhrajyoti Datta <[email protected]>
Add get serial id if not provided
Signed-off-by: Shubhrajyoti Datta <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
drivers/tty/serial/uartlite.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 77bc9d0..441a216 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -763,6 +763,13 @@ static int ulite_probe(struct platform_device *pdev)
if (prop)
id = be32_to_cpup(prop);
#endif
+ if (id < 0) {
+ /* Look for a serialN alias */
+ id = of_alias_get_id(pdev->dev.of_node, "serial");
+ if (id < 0)
+ id = 0;
+ }
+
if (!ulite_uart_driver.state) {
dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n");
ret = uart_register_driver(&ulite_uart_driver);
--
2.1.1
From: Shubhrajyoti Datta <[email protected]>
Remove SERIAL_UARTLITE_NR_UARTS from Kconfig as it is unused.
Signed-off-by: Shubhrajyoti Datta <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
drivers/tty/serial/Kconfig | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 32886c3..dc34d43 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -543,15 +543,6 @@ config SERIAL_UARTLITE_CONSOLE
console (the system console is the device which receives all kernel
messages and warnings and which allows logins in single user mode).
-config SERIAL_UARTLITE_NR_UARTS
- int "Maximum number of uartlite serial ports"
- depends on SERIAL_UARTLITE
- range 1 256
- default 1
- help
- Set this to the number of uartlites in your system, or the number
- you think you might implement.
-
config SERIAL_SUNCORE
bool
depends on SPARC
--
2.1.1
From: Shubhrajyoti Datta <[email protected]>
This patch is removing ULITE_NR_PORTS macro which limits number of
ports which can be used. Every instance is registering own struct
uart_driver with minor number which corresponds to alias ID (or 0 now).
and with 1 uart port. The same alias ID is saved to
tty_driver->name_base which is key field for creating ttyULX name.
Because name_base and minor number are setup already there is no need to
setup any port->line number because 0 is the right value.
Signed-off-by: Shubhrajyoti Datta <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
v2:
Remove the stray unrelated changes
v3:
Fix a compile error
drivers/tty/serial/uartlite.c | 249 ++++++++++++++++++++++++++++++------------
1 file changed, 179 insertions(+), 70 deletions(-)
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 20fe11f..a118b8e 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -27,7 +27,6 @@
#define ULITE_NAME "ttyUL"
#define ULITE_MAJOR 204
#define ULITE_MINOR 187
-#define ULITE_NR_UARTS CONFIG_SERIAL_UARTLITE_NR_UARTS
/* ---------------------------------------------------------------------
* Register definitions
@@ -65,6 +64,7 @@ static struct uart_port *console_port;
struct uartlite_data {
const struct uartlite_reg_ops *reg_ops;
struct clk *clk;
+ int id;
struct uart_driver *ulite_uart_driver;
};
@@ -117,7 +117,6 @@ static inline void uart_out32(u32 val, u32 offset, struct uart_port *port)
pdata->reg_ops->out(val, port->membase + offset);
}
-static struct uart_port ulite_ports[ULITE_NR_UARTS];
/* ---------------------------------------------------------------------
* Core UART driver operations
@@ -535,18 +534,6 @@ static int ulite_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-static struct uart_driver ulite_uart_driver;
-
-static struct console ulite_console = {
- .name = ULITE_NAME,
- .write = ulite_console_write,
- .device = uart_console_device,
- .setup = ulite_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1, /* Specified on the cmdline (e.g. console=ttyUL0 ) */
- .data = &ulite_uart_driver,
-};
-
static void early_uartlite_putc(struct uart_port *port, int c)
{
/*
@@ -590,18 +577,6 @@ OF_EARLYCON_DECLARE(uartlite_a, "xlnx,xps-uartlite-1.00.a", early_uartlite_setup
#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
-static struct uart_driver ulite_uart_driver = {
- .owner = THIS_MODULE,
- .driver_name = "uartlite",
- .dev_name = ULITE_NAME,
- .major = ULITE_MAJOR,
- .minor = ULITE_MINOR,
- .nr = ULITE_NR_UARTS,
-#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
- .cons = &ulite_console,
-#endif
-};
-
/* ---------------------------------------------------------------------
* Port assignment functions (mapping devices to uart_port structures)
*/
@@ -622,24 +597,9 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq,
struct uart_port *port;
int rc;
- /* if id = -1; then scan for a free id and use that */
- if (id < 0) {
- for (id = 0; id < ULITE_NR_UARTS; id++)
- if (ulite_ports[id].mapbase == 0)
- break;
- }
- if (id < 0 || id >= ULITE_NR_UARTS) {
- dev_err(dev, "%s%i too large\n", ULITE_NAME, id);
- return -EINVAL;
- }
-
- if ((ulite_ports[id].mapbase) && (ulite_ports[id].mapbase != base)) {
- dev_err(dev, "cannot assign to %s%i; it is already in use\n",
- ULITE_NAME, id);
- return -EBUSY;
- }
-
- port = &ulite_ports[id];
+ port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
spin_lock_init(&port->lock);
port->fifosize = 16;
@@ -653,7 +613,6 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq,
port->flags = UPF_BOOT_AUTOCONF;
port->dev = dev;
port->type = PORT_UNKNOWN;
- port->line = id;
port->private_data = pdata;
dev_set_drvdata(dev, port);
@@ -778,11 +737,24 @@ static const struct of_device_id ulite_of_match[] = {
MODULE_DEVICE_TABLE(of, ulite_of_match);
#endif /* CONFIG_OF */
-static int ulite_probe(struct platform_device *pdev)
+/*
+ * 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 256
+
+/* 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 ulite_get_id(struct platform_device *pdev)
{
- struct resource *res;
- struct uartlite_data *pdata;
- int irq, ret;
+ int ret;
int id = pdev->id;
#ifdef CONFIG_OF
const __be32 *prop;
@@ -790,40 +762,158 @@ static int ulite_probe(struct platform_device *pdev)
prop = of_get_property(pdev->dev.of_node, "port-number", NULL);
if (prop)
id = be32_to_cpup(prop);
+
+ /* Alias list is stable that's why get alias bitmap only once */
+ if (!alias_bitmap_initialized) {
+ ret = of_alias_get_alias_list(ulite_of_match, "serial",
+ alias_bitmap, MAX_UART_INSTANCES);
+ if (ret)
+ return ret;
+
+ alias_bitmap_initialized++;
+ }
+
#endif
- if (id < 0) {
- /* Look for a serialN alias */
+
+ mutex_lock(&bitmap_lock);
+
+ /* 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 */
+ if (id < 0)
id = of_alias_get_id(pdev->dev.of_node, "serial");
- if (id < 0)
- id = 0;
- }
- if (!ulite_uart_driver.state) {
- dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n");
- ret = uart_register_driver(&ulite_uart_driver);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to register driver\n");
- return ret;
+ 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;
+}
+
+static int ulite_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct uartlite_data *pdata;
+ int irq, ret;
+ struct uart_driver *ulite_uart_driver;
+ char *driver_name;
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+ struct console *ulite_console;
+#endif
+
pdata = devm_kzalloc(&pdev->dev, sizeof(struct uartlite_data),
GFP_KERNEL);
if (!pdata)
return -ENOMEM;
+ ulite_uart_driver = devm_kzalloc(&pdev->dev,
+ sizeof(*ulite_uart_driver),
+ GFP_KERNEL);
+ if (!ulite_uart_driver)
+ return -ENOMEM;
+
+ pdata->id = ulite_get_id(pdev);
+ if (pdata->id < 0)
+ return pdata->id;
+
+ /* There is a need to use unique driver name */
+ driver_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s%d",
+ ULITE_NAME, pdata->id);
+ if (!driver_name) {
+ ret = -ENOMEM;
+ goto err_out_id;
+ }
+
+ ulite_uart_driver->owner = THIS_MODULE;
+ ulite_uart_driver->driver_name = driver_name;
+ ulite_uart_driver->dev_name = ULITE_NAME;
+ ulite_uart_driver->major = ULITE_MAJOR;
+ ulite_uart_driver->minor = pdata->id;
+ ulite_uart_driver->nr = 1;
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+ ulite_console = devm_kzalloc(&pdev->dev, sizeof(*ulite_console),
+ GFP_KERNEL);
+ if (!ulite_console) {
+ ret = -ENOMEM;
+ goto err_out_id;
+ }
+
+ strncpy(ulite_console->name, ULITE_NAME,
+ sizeof(ulite_console->name));
+ ulite_console->index = pdata->id;
+ ulite_console->write = ulite_console_write;
+ ulite_console->device = uart_console_device;
+ ulite_console->setup = ulite_console_setup;
+ ulite_console->flags = CON_PRINTBUFFER;
+ ulite_uart_driver->cons = ulite_console;
+ ulite_console->data = ulite_uart_driver;
+#endif
+
+ dev_dbg(&pdev->dev, "uartlite: calling uart_register_driver()\n");
+ ret = uart_register_driver(ulite_uart_driver);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register driver\n");
+ goto err_out_id;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
+ if (!res) {
+ ret = -ENODEV;
+ goto err_out_unregister_driver;
+ }
irq = platform_get_irq(pdev, 0);
- if (irq <= 0)
- return -ENXIO;
+ if (irq <= 0) {
+ ret = -ENXIO;
+ goto err_out_unregister_driver;
+ }
pdata->clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
if (IS_ERR(pdata->clk)) {
- if (PTR_ERR(pdata->clk) != -ENOENT)
- return PTR_ERR(pdata->clk);
+ if (PTR_ERR(pdata->clk) != -ENOENT) {
+ ret = PTR_ERR(pdata->clk);
+ goto err_out_unregister_driver;
+ }
/*
* Clock framework support is optional, continue on
@@ -832,11 +922,10 @@ static int ulite_probe(struct platform_device *pdev)
pdata->clk = NULL;
}
- pdata->ulite_uart_driver = &ulite_uart_driver;
ret = clk_prepare_enable(pdata->clk);
if (ret) {
dev_err(&pdev->dev, "Failed to prepare clock\n");
- return ret;
+ goto err_out_unregister_driver;
}
pm_runtime_use_autosuspend(&pdev->dev);
@@ -844,11 +933,27 @@ static int ulite_probe(struct platform_device *pdev)
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
- ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata);
+ ulite_uart_driver->tty_driver->name_base = pdata->id;
+ pdata->ulite_uart_driver = ulite_uart_driver;
+ ret = ulite_assign(&pdev->dev, pdata->id, res->start, irq, pdata);
+ if (ret < 0)
+ goto err_out_clk_disable;
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
+ return 0;
+err_out_clk_disable:
+ clk_disable_unprepare(pdata->clk);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
+err_out_unregister_driver:
+ uart_unregister_driver(pdata->ulite_uart_driver);
+err_out_id:
+ mutex_lock(&bitmap_lock);
+ clear_bit(pdata->id, bitmap);
+ mutex_unlock(&bitmap_lock);
return ret;
}
@@ -860,11 +965,16 @@ static int ulite_remove(struct platform_device *pdev)
clk_unprepare(pdata->clk);
rc = ulite_release(&pdev->dev);
+ mutex_lock(&bitmap_lock);
+ clear_bit(pdata->id, bitmap);
+ mutex_unlock(&bitmap_lock);
+
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
if (console_port == port)
console_port = NULL;
#endif
+ uart_unregister_driver(pdata->ulite_uart_driver);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
@@ -898,7 +1008,6 @@ static int __init ulite_init(void)
static void __exit ulite_exit(void)
{
platform_driver_unregister(&ulite_platform_driver);
- uart_unregister_driver(&ulite_uart_driver);
}
module_init(ulite_init);
--
2.1.1
From: Shubhrajyoti Datta <[email protected]>
Remove the use of the static uartlite structure.
Signed-off-by: Shubhrajyoti Datta <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
drivers/tty/serial/uartlite.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 9c99a1d9..20fe11f 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -670,7 +670,7 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq,
#endif
/* Register the port */
- rc = uart_add_one_port(&ulite_uart_driver, port);
+ rc = uart_add_one_port(pdata->ulite_uart_driver, port);
if (rc) {
dev_err(dev, "uart_add_one_port() failed; err=%i\n", rc);
port->mapbase = 0;
@@ -681,7 +681,7 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq,
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
/* This is not port which is used for console that's why clean it up */
if (console_port == port &&
- !(ulite_uart_driver->cons->flags & CON_ENABLED))
+ !(pdata->ulite_uart_driver->cons->flags & CON_ENABLED))
console_port = NULL;
#endif
--
2.1.1
Hi Shubhrajyoti,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on tty/tty-testing]
[also build test ERROR on next-20181016]
[cannot apply to v4.19-rc8]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/shubhrajyoti-datta-gmail-com/serial-uartlite-Add-support-for-dynamic-allocation/20181016-210709
base: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-testing
config: i386-randconfig-x019-201841 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
Note: the linux-review/shubhrajyoti-datta-gmail-com/serial-uartlite-Add-support-for-dynamic-allocation/20181016-210709 HEAD 7aba44c5f67836025decfe4dc4ab364c1f83f44d builds fine.
It only hurts bisectibility.
All error/warnings (new ones prefixed by >>):
In file included from include/linux/ioport.h:13:0,
from include/linux/device.h:15,
from include/linux/platform_device.h:14,
from drivers/tty//serial/uartlite.c:9:
drivers/tty//serial/uartlite.c: In function 'ulite_assign':
>> drivers/tty//serial/uartlite.c:684:25: error: invalid type argument of '->' (have 'struct uart_driver')
!(ulite_uart_driver->cons->flags & CON_ENABLED))
^
include/linux/compiler.h:58:30: note: in definition of macro '__trace_if'
if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
^~~~
>> drivers/tty//serial/uartlite.c:683:2: note: in expansion of macro 'if'
if (console_port == port &&
^~
>> drivers/tty//serial/uartlite.c:684:25: error: invalid type argument of '->' (have 'struct uart_driver')
!(ulite_uart_driver->cons->flags & CON_ENABLED))
^
include/linux/compiler.h:58:42: note: in definition of macro '__trace_if'
if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
^~~~
>> drivers/tty//serial/uartlite.c:683:2: note: in expansion of macro 'if'
if (console_port == port &&
^~
>> drivers/tty//serial/uartlite.c:684:25: error: invalid type argument of '->' (have 'struct uart_driver')
!(ulite_uart_driver->cons->flags & CON_ENABLED))
^
include/linux/compiler.h:69:16: note: in definition of macro '__trace_if'
______r = !!(cond); \
^~~~
>> drivers/tty//serial/uartlite.c:683:2: note: in expansion of macro 'if'
if (console_port == port &&
^~
vim +684 drivers/tty//serial/uartlite.c
671
672 /* Register the port */
673 rc = uart_add_one_port(&ulite_uart_driver, port);
674 if (rc) {
675 dev_err(dev, "uart_add_one_port() failed; err=%i\n", rc);
676 port->mapbase = 0;
677 dev_set_drvdata(dev, NULL);
678 return rc;
679 }
680
681 #ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
682 /* This is not port which is used for console that's why clean it up */
> 683 if (console_port == port &&
> 684 !(ulite_uart_driver->cons->flags & CON_ENABLED))
685 console_port = NULL;
686 #endif
687
688 return 0;
689 }
690
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
On Tue, Oct 16, 2018 at 03:47:59PM +0530, [email protected] wrote:
> From: Shubhrajyoti Datta <[email protected]>
>
> Currently the number of uarts are configured through a Kconfig
> option Make it dynamic.
> While at it adapt to the runtime framework.
>
> It is based a similar series on the uartps from Michal
I've applied the first 5, can you fix up the rest and resend so that
they do not cause build breakage at any point?
thanks,
greg k-h