diff options
-rw-r--r-- | drivers/remoteproc/remoteproc_core.c | 66 |
1 files changed, 39 insertions, 27 deletions
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 80056513ae71..4dee63f319ba 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1979,6 +1979,33 @@ static const struct device_type rproc_type = { .release = rproc_type_release, }; +static int rproc_alloc_firmware(struct rproc *rproc, + const char *name, const char *firmware) +{ + char *p, *template = "rproc-%s-fw"; + int name_len; + + if (!firmware) { + /* + * If the caller didn't pass in a firmware name then + * construct a default name. + */ + name_len = strlen(name) + strlen(template) - 2 + 1; + p = kmalloc(name_len, GFP_KERNEL); + if (!p) + return -ENOMEM; + snprintf(p, name_len, template, name); + } else { + p = kstrdup(firmware, GFP_KERNEL); + if (!p) + return -ENOMEM; + } + + rproc->firmware = p; + + return 0; +} + /** * rproc_alloc() - allocate a remote processor handle * @dev: the underlying device @@ -2007,42 +2034,21 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, const char *firmware, int len) { struct rproc *rproc; - char *p, *template = "rproc-%s-fw"; - int name_len; if (!dev || !name || !ops) return NULL; - if (!firmware) { - /* - * If the caller didn't pass in a firmware name then - * construct a default name. - */ - name_len = strlen(name) + strlen(template) - 2 + 1; - p = kmalloc(name_len, GFP_KERNEL); - if (!p) - return NULL; - snprintf(p, name_len, template, name); - } else { - p = kstrdup(firmware, GFP_KERNEL); - if (!p) - return NULL; - } - rproc = kzalloc(sizeof(struct rproc) + len, GFP_KERNEL); - if (!rproc) { - kfree(p); + if (!rproc) return NULL; - } + + if (rproc_alloc_firmware(rproc, name, firmware)) + goto free_rproc; rproc->ops = kmemdup(ops, sizeof(*ops), GFP_KERNEL); - if (!rproc->ops) { - kfree(p); - kfree(rproc); - return NULL; - } + if (!rproc->ops) + goto free_firmware; - rproc->firmware = p; rproc->name = name; rproc->priv = &rproc[1]; rproc->auto_boot = true; @@ -2091,6 +2097,12 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, rproc->state = RPROC_OFFLINE; return rproc; + +free_firmware: + kfree(rproc->firmware); +free_rproc: + kfree(rproc); + return NULL; } EXPORT_SYMBOL(rproc_alloc); |