123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- From 5b587496dc63595b71265d986ce69728c2724370 Mon Sep 17 00:00:00 2001
- From: Hans de Goede <[email protected]>
- Date: Wed, 10 Oct 2018 13:00:59 +0200
- Subject: [PATCH] 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 <[email protected]>
- Signed-off-by: Kalle Valo <[email protected]>
- ---
- .../broadcom/brcm80211/brcmfmac/firmware.c | 65 +++++++---------------
- 1 file changed, 19 insertions(+), 46 deletions(-)
- --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
- +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
- @@ -532,33 +532,6 @@ static int brcmf_fw_complete_request(con
- 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;
- @@ -568,26 +541,19 @@ static void brcmf_fw_request_done(const
- 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;
- -
- -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:
- + 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);
- + }
- +
- + 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);
- }
- @@ -611,7 +577,9 @@ int brcmf_fw_get_firmwares(struct device
- 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)
- @@ -628,7 +596,12 @@ int brcmf_fw_get_firmwares(struct device
- 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;
- }
-
|