82 lines
2.6 KiB
Diff
82 lines
2.6 KiB
Diff
|
From 0b5c0305e57ca940713bcb2b202fd2b412c62f31 Mon Sep 17 00:00:00 2001
|
||
|
From: Arend Van Spriel <arend.vanspriel@broadcom.com>
|
||
|
Date: Tue, 3 Apr 2018 10:18:15 +0200
|
||
|
Subject: [PATCH] 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: d09ae51a4b67 ("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>
|
||
|
---
|
||
|
.../broadcom/brcm80211/brcmfmac/firmware.c | 36 ++++++++++++----------
|
||
|
1 file changed, 20 insertions(+), 16 deletions(-)
|
||
|
|
||
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
|
||
|
@@ -459,7 +459,7 @@ static void brcmf_fw_free_request(struct
|
||
|
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_item *cur;
|
||
|
@@ -498,13 +498,10 @@ static void brcmf_fw_request_nvram_done(
|
||
|
brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length);
|
||
|
cur->nv_data.data = nvram;
|
||
|
cur->nv_data.len = nvram_length;
|
||
|
- return;
|
||
|
+ return 0;
|
||
|
|
||
|
fail:
|
||
|
- brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
|
||
|
- fwctx->done(fwctx->dev, -ENOENT, NULL);
|
||
|
- brcmf_fw_free_request(fwctx->req);
|
||
|
- kfree(fwctx);
|
||
|
+ return -ENOENT;
|
||
|
}
|
||
|
|
||
|
static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async)
|
||
|
@@ -553,20 +550,27 @@ static void brcmf_fw_request_done(const
|
||
|
brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path,
|
||
|
fw ? "" : "not ");
|
||
|
|
||
|
- 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)) {
|
||
|
+ if (!fw)
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
+ if (ret < 0 && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
|
||
|
+ goto fail;
|
||
|
+
|
||
|
do {
|
||
|
if (++fwctx->curpos == fwctx->req->n_items) {
|
||
|
ret = 0;
|