serial: pl010: Move uart_register_driver call to device probe

uart_register_driver call binds the driver to a specific device
node through tty_register_driver call. This should typically
happen during device probe call.

In a multiplatform scenario, it is possible that multiple serial
drivers are part of the kernel. Currently the driver registration fails
if multiple serial drivers with overlapping major/minor numbers are
included.

Signed-off-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Sjoerd Simons 2017-04-20 14:13:00 +02:00 committed by Greg Kroah-Hartman
parent 1cf4a7efdc
commit bd8766b158

View File

@ -697,6 +697,7 @@ static struct console amba_console = {
#define AMBA_CONSOLE NULL
#endif
static DEFINE_MUTEX(amba_reg_lock);
static struct uart_driver amba_reg = {
.owner = THIS_MODULE,
.driver_name = "ttyAM",
@ -749,6 +750,19 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
amba_ports[i] = uap;
amba_set_drvdata(dev, uap);
mutex_lock(&amba_reg_lock);
if (!amba_reg.state) {
ret = uart_register_driver(&amba_reg);
if (ret < 0) {
mutex_unlock(&amba_reg_lock);
dev_err(uap->port.dev,
"Failed to register AMBA-PL010 driver\n");
return ret;
}
}
mutex_unlock(&amba_reg_lock);
ret = uart_add_one_port(&amba_reg, &uap->port);
if (ret)
amba_ports[i] = NULL;
@ -760,12 +774,18 @@ static int pl010_remove(struct amba_device *dev)
{
struct uart_amba_port *uap = amba_get_drvdata(dev);
int i;
bool busy = false;
uart_remove_one_port(&amba_reg, &uap->port);
for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
if (amba_ports[i] == uap)
amba_ports[i] = NULL;
else if (amba_ports[i])
busy = true;
if (!busy)
uart_unregister_driver(&amba_reg);
return 0;
}
@ -816,23 +836,14 @@ static struct amba_driver pl010_driver = {
static int __init pl010_init(void)
{
int ret;
printk(KERN_INFO "Serial: AMBA driver\n");
ret = uart_register_driver(&amba_reg);
if (ret == 0) {
ret = amba_driver_register(&pl010_driver);
if (ret)
uart_unregister_driver(&amba_reg);
}
return ret;
return amba_driver_register(&pl010_driver);
}
static void __exit pl010_exit(void)
{
amba_driver_unregister(&pl010_driver);
uart_unregister_driver(&amba_reg);
}
module_init(pl010_init);