summaryrefslogtreecommitdiffstats
path: root/0002-brcmfmac-Remove-recursion-from-firmware-load-error-h.patch
blob: a0553e6e809e9d207587f8a39a21b34903b6e4b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
From 7a2f4b4fa44268a570f6fa7782385741134f8da6 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 27 Sep 2018 17:51:36 +0200
Subject: [PATCH 2/5] brcmfmac: Remove recursion from firmware load error
 handling

Before this commit brcmf_fw_request_done would call
brcmf_fw_request_next_item to load the next item, which on an error would
call brcmf_fw_request_done, which if the error is recoverable (*) will
then continue calling brcmf_fw_request_next_item for the next item again
which on an error will call brcmf_fw_request_done again...

This does not blow up because we only have a limited number of items so
we never recurse too deep. But the recursion is still quite ugly and
frankly is giving me a headache, so lets fix this.

This commit fixes this by removing brcmf_fw_request_next_item and by
making brcmf_fw_get_firmwares and brcmf_fw_request_done directly call
firmware_request_nowait resp. firmware_request themselves.

*) brcmf_fw_request_nvram_done fallback path succeeds or
   BRCMF_FW_REQF_OPTIONAL is set

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 .../broadcom/brcm80211/brcmfmac/firmware.c    | 65 ++++++-------------
 1 file changed, 19 insertions(+), 46 deletions(-)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index 848c3351d107..13d051cd0fcf 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -615,33 +615,6 @@ static int brcmf_fw_complete_request(const struct firmware *fw,
 	return (cur->flags & BRCMF_FW_REQF_OPTIONAL) ? 0 : ret;
 }
 
-static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async)
-{
-	struct brcmf_fw_item *cur;
-	const struct firmware *fw = NULL;
-	int ret;
-
-	cur = &fwctx->req->items[fwctx->curpos];
-
-	brcmf_dbg(TRACE, "%srequest for %s\n", async ? "async " : "",
-		  cur->path);
-
-	if (async)
-		ret = request_firmware_nowait(THIS_MODULE, true, cur->path,
-					      fwctx->dev, GFP_KERNEL, fwctx,
-					      brcmf_fw_request_done);
-	else
-		ret = request_firmware(&fw, cur->path, fwctx->dev);
-
-	if (ret < 0) {
-		brcmf_fw_request_done(NULL, fwctx);
-	} else if (!async && fw) {
-		brcmf_fw_complete_request(fw, fwctx);
-		return -EAGAIN;
-	}
-	return 0;
-}
-
 static void brcmf_fw_request_done(const struct firmware *fw, void *ctx)
 {
 	struct brcmf_fw *fwctx = ctx;
@@ -651,26 +624,19 @@ static void brcmf_fw_request_done(const struct firmware *fw, void *ctx)
 	cur = &fwctx->req->items[fwctx->curpos];
 
 	ret = brcmf_fw_complete_request(fw, fwctx);
-	if (ret < 0)
-		goto fail;
-
-	do {
-		if (++fwctx->curpos == fwctx->req->n_items) {
-			ret = 0;
-			goto done;
-		}
 
-		ret = brcmf_fw_request_next_item(fwctx, false);
-	} while (ret == -EAGAIN);
-
-	return;
+	while (ret == 0 && ++fwctx->curpos < fwctx->req->n_items) {
+		cur = &fwctx->req->items[fwctx->curpos];
+		request_firmware(&fw, cur->path, fwctx->dev);
+		ret = brcmf_fw_complete_request(fw, ctx);
+	}
 
-fail:
-	brcmf_dbg(TRACE, "failed err=%d: dev=%s, fw=%s\n", ret,
-		  dev_name(fwctx->dev), cur->path);
-	brcmf_fw_free_request(fwctx->req);
-	fwctx->req = NULL;
-done:
+	if (ret) {
+		brcmf_dbg(TRACE, "failed err=%d: dev=%s, fw=%s\n", ret,
+			  dev_name(fwctx->dev), cur->path);
+		brcmf_fw_free_request(fwctx->req);
+		fwctx->req = NULL;
+	}
 	fwctx->done(fwctx->dev, ret, fwctx->req);
 	kfree(fwctx);
 }
@@ -694,7 +660,9 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
 			   void (*fw_cb)(struct device *dev, int err,
 					 struct brcmf_fw_request *req))
 {
+	struct brcmf_fw_item *first = &req->items[0];
 	struct brcmf_fw *fwctx;
+	int ret;
 
 	brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
 	if (!fw_cb)
@@ -711,7 +679,12 @@ int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
 	fwctx->req = req;
 	fwctx->done = fw_cb;
 
-	brcmf_fw_request_next_item(fwctx, true);
+	ret = request_firmware_nowait(THIS_MODULE, true, first->path,
+				      fwctx->dev, GFP_KERNEL, fwctx,
+				      brcmf_fw_request_done);
+	if (ret < 0)
+		brcmf_fw_request_done(NULL, fwctx);
+
 	return 0;
 }
 
-- 
2.19.0