Skip to content

Commit

Permalink
drivers: PL011: avoid potential unregister_driver call
Browse files Browse the repository at this point in the history
Although we care about not unregistering the driver if there are
still ports connected during the .remove callback, we do miss this
check in the pl011_probe function. So if the current port allocation
fails, but there are other ports already registered, we will kill
those.
So factor out the port removal into a separate function and use that
in the probe function, too.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Tested-by: Mark Langsdorf <mlangsdo@redhat.com>
Tested-by: Naresh Bhat <nbhat@cavium.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Andre Przywara authored and Greg Kroah-Hartman committed May 24, 2015
1 parent 7798ede commit 49bb3c8
Showing 1 changed file with 20 additions and 16 deletions.
36 changes: 20 additions & 16 deletions drivers/tty/serial/amba-pl011.c
Original file line number Diff line number Diff line change
Expand Up @@ -2135,6 +2135,23 @@ static int pl011_probe_dt_alias(int index, struct device *dev)
return ret;
}

/* unregisters the driver also if no more ports are left */
static void pl011_unregister_port(struct uart_amba_port *uap)
{
int i;
bool busy = false;

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;
}
pl011_dma_remove(uap);
if (!busy)
uart_unregister_driver(&amba_reg);
}

static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
{
struct uart_amba_port *uap;
Expand Down Expand Up @@ -2200,31 +2217,18 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
}

ret = uart_add_one_port(&amba_reg, &uap->port);
if (ret) {
amba_ports[i] = NULL;
uart_unregister_driver(&amba_reg);
}
if (ret)
pl011_unregister_port(uap);

return ret;
}

static int pl011_remove(struct amba_device *dev)
{
struct uart_amba_port *uap = amba_get_drvdata(dev);
bool busy = false;
int i;

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;

pl011_dma_remove(uap);
if (!busy)
uart_unregister_driver(&amba_reg);
pl011_unregister_port(uap);
return 0;
}

Expand Down

0 comments on commit 49bb3c8

Please sign in to comment.