diff options
author | Johan Hovold <johan@kernel.org> | 2017-10-12 15:28:18 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-10-23 11:25:48 +0200 |
commit | 978d6fac5d0617c9722ae1db1accee46776f4400 (patch) | |
tree | 3c1153ded6911d27552cdec2c0edf978ada8f92d /drivers/tty/serdev | |
parent | 08fcee289f341786eb3b44e5f2d1dc850943238e (diff) | |
download | linux-978d6fac5d0617c9722ae1db1accee46776f4400.tar.gz linux-978d6fac5d0617c9722ae1db1accee46776f4400.tar.bz2 linux-978d6fac5d0617c9722ae1db1accee46776f4400.zip |
serdev: fix controller-allocation error handling
Reorder controller initialisation so that in the unlikely event that id
allocation fails, we don't end up releasing id 0 in the destructor.
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serdev')
-rw-r--r-- | drivers/tty/serdev/core.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index dde2ddc5967d..4d662d1f4784 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -358,26 +358,31 @@ struct serdev_controller *serdev_controller_alloc(struct device *parent, if (!ctrl) return NULL; - device_initialize(&ctrl->dev); - ctrl->dev.type = &serdev_ctrl_type; - ctrl->dev.bus = &serdev_bus_type; - ctrl->dev.parent = parent; - ctrl->dev.of_node = parent->of_node; - serdev_controller_set_drvdata(ctrl, &ctrl[1]); - id = ida_simple_get(&ctrl_ida, 0, 0, GFP_KERNEL); if (id < 0) { dev_err(parent, "unable to allocate serdev controller identifier.\n"); - serdev_controller_put(ctrl); - return NULL; + goto err_free; } ctrl->nr = id; + + device_initialize(&ctrl->dev); + ctrl->dev.type = &serdev_ctrl_type; + ctrl->dev.bus = &serdev_bus_type; + ctrl->dev.parent = parent; + ctrl->dev.of_node = parent->of_node; + serdev_controller_set_drvdata(ctrl, &ctrl[1]); + dev_set_name(&ctrl->dev, "serial%d", id); dev_dbg(&ctrl->dev, "allocated controller 0x%p id %d\n", ctrl, id); return ctrl; + +err_free: + kfree(ctrl); + + return NULL; } EXPORT_SYMBOL_GPL(serdev_controller_alloc); |