It backports remaining brcmfmac changes from 4.17. Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
		
			
				
	
	
		
			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;
 |