brcmfmac: fix firmware request processing if nvram load fails

When nvram loading fails a double free occurred. Fix this and reorg the
code a little.

Fixes: d09ae51a4b ("brcmfmac: pass struct in brcmf_fw_get_firmwares()")
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
Arend Van Spriel 2018-04-03 10:18:15 +02:00 committed by Kalle Valo
parent 4608f06453
commit 0b5c0305e5
1 changed files with 20 additions and 16 deletions

View File

@ -459,7 +459,7 @@ static void brcmf_fw_free_request(struct brcmf_fw_request *req)
kfree(req); kfree(req);
} }
static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
{ {
struct brcmf_fw *fwctx = ctx; struct brcmf_fw *fwctx = ctx;
struct brcmf_fw_item *cur; struct brcmf_fw_item *cur;
@ -498,13 +498,10 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length); brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length);
cur->nv_data.data = nvram; cur->nv_data.data = nvram;
cur->nv_data.len = nvram_length; cur->nv_data.len = nvram_length;
return; return 0;
fail: fail:
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); return -ENOENT;
fwctx->done(fwctx->dev, -ENOENT, NULL);
brcmf_fw_free_request(fwctx->req);
kfree(fwctx);
} }
static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async) static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async)
@ -553,20 +550,27 @@ static void brcmf_fw_request_done(const struct firmware *fw, void *ctx)
brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path, brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path,
fw ? "" : "not "); fw ? "" : "not ");
if (fw) { if (!fw)
if (cur->type == BRCMF_FW_TYPE_BINARY)
cur->binary = fw;
else if (cur->type == BRCMF_FW_TYPE_NVRAM)
brcmf_fw_request_nvram_done(fw, fwctx);
else
release_firmware(fw);
} else if (cur->type == BRCMF_FW_TYPE_NVRAM) {
brcmf_fw_request_nvram_done(NULL, fwctx);
} else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL)) {
ret = -ENOENT; ret = -ENOENT;
switch (cur->type) {
case BRCMF_FW_TYPE_NVRAM:
ret = brcmf_fw_request_nvram_done(fw, fwctx);
break;
case BRCMF_FW_TYPE_BINARY:
cur->binary = fw;
break;
default:
/* something fishy here so bail out early */
brcmf_err("unknown fw type: %d\n", cur->type);
release_firmware(fw);
ret = -EINVAL;
goto fail; goto fail;
} }
if (ret < 0 && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
goto fail;
do { do {
if (++fwctx->curpos == fwctx->req->n_items) { if (++fwctx->curpos == fwctx->req->n_items) {
ret = 0; ret = 0;