diff options
author | Arend Van Spriel <arend.vanspriel@broadcom.com> | 2018-03-22 21:28:26 +0100 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2018-03-27 11:04:30 +0200 |
commit | d09ae51a4b676151edaf572bcd5f272b5532639f (patch) | |
tree | 9a0346049ba43ea205e8c48b17692077558a4175 /drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | |
parent | brcmfmac: derive firmware filenames from basename mapping (diff) | |
download | linux-d09ae51a4b676151edaf572bcd5f272b5532639f.tar.xz linux-d09ae51a4b676151edaf572bcd5f272b5532639f.zip |
brcmfmac: pass struct in brcmf_fw_get_firmwares()
Make the function brcmf_fw_get_firmwares() a bit more easy to extend
using a structure to pass the request parameters.
Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Reviewed-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c')
-rw-r--r-- | drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 175 |
1 files changed, 120 insertions, 55 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 6945f582dbb7..95004dbba942 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -438,18 +438,31 @@ void brcmf_fw_nvram_free(void *nvram) struct brcmf_fw { struct device *dev; - u16 flags; - const struct firmware *code; - const char *nvram_name; - u16 domain_nr; - u16 bus_nr; - void (*done)(struct device *dev, int err, const struct firmware *fw, - void *nvram_image, u32 nvram_len); + struct brcmf_fw_request *req; + u32 curpos; + void (*done)(struct device *dev, int err, struct brcmf_fw_request *req); }; +static void brcmf_fw_request_done(const struct firmware *fw, void *ctx); + +static void brcmf_fw_free_request(struct brcmf_fw_request *req) +{ + struct brcmf_fw_item *item; + int i; + + for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) { + if (item->type == BRCMF_FW_TYPE_BINARY) + release_firmware(item->binary); + else if (item->type == BRCMF_FW_TYPE_NVRAM) + brcmf_fw_nvram_free(item->nv_data.data); + } + kfree(req); +} + static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) { struct brcmf_fw *fwctx = ctx; + struct brcmf_fw_item *cur; u32 nvram_length = 0; void *nvram = NULL; u8 *data = NULL; @@ -457,83 +470,150 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) bool raw_nvram; brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev)); + + cur = &fwctx->req->items[fwctx->curpos]; + if (fw && fw->data) { data = (u8 *)fw->data; data_len = fw->size; raw_nvram = false; } else { data = bcm47xx_nvram_get_contents(&data_len); - if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) + if (!data && !(cur->flags & BRCMF_FW_REQF_OPTIONAL)) goto fail; raw_nvram = true; } if (data) nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length, - fwctx->domain_nr, fwctx->bus_nr); + fwctx->req->domain_nr, + fwctx->req->bus_nr); if (raw_nvram) bcm47xx_nvram_release_contents(data); release_firmware(fw); - if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) + if (!nvram && !(cur->flags & BRCMF_FW_REQF_OPTIONAL)) goto fail; - fwctx->done(fwctx->dev, 0, fwctx->code, nvram, nvram_length); - kfree(fwctx); + brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length); + cur->nv_data.data = nvram; + cur->nv_data.len = nvram_length; return; fail: brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); - release_firmware(fwctx->code); - fwctx->done(fwctx->dev, -ENOENT, NULL, NULL, 0); + fwctx->done(fwctx->dev, -ENOENT, NULL); + brcmf_fw_free_request(fwctx->req); kfree(fwctx); } -static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx) +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_dbg(TRACE, "firmware %s %sfound\n", cur->path, + fw ? "" : "not "); + 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); + + return -EAGAIN; + } + return 0; +} + +static void brcmf_fw_request_done(const struct firmware *fw, void *ctx) { struct brcmf_fw *fwctx = ctx; + struct brcmf_fw_item *cur; int ret = 0; - brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev)); - if (!fw) { + cur = &fwctx->req->items[fwctx->curpos]; + + 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)) { ret = -ENOENT; goto fail; } - /* only requested code so done here */ - if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) - goto done; - fwctx->code = fw; - ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name, - fwctx->dev, GFP_KERNEL, fwctx, - brcmf_fw_request_nvram_done); + do { + if (++fwctx->curpos == fwctx->req->n_items) { + ret = 0; + goto done; + } + + ret = brcmf_fw_request_next_item(fwctx, false); + } while (ret == -EAGAIN); - /* pass NULL to nvram callback for bcm47xx fallback */ - if (ret) - brcmf_fw_request_nvram_done(NULL, fwctx); return; fail: - brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); + 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: - fwctx->done(fwctx->dev, ret, fw, NULL, 0); + fwctx->done(fwctx->dev, ret, fwctx->req); kfree(fwctx); } -int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, - const char *code, const char *nvram, - void (*fw_cb)(struct device *dev, int err, - const struct firmware *fw, - void *nvram_image, u32 nvram_len), - u16 domain_nr, u16 bus_nr) +static bool brcmf_fw_request_is_valid(struct brcmf_fw_request *req) +{ + struct brcmf_fw_item *item; + int i; + + if (!req->n_items) + return false; + + for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) { + if (!item->path) + return false; + } + return true; +} + +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 *fwctx; brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev)); - if (!fw_cb || !code) + if (!fw_cb) return -EINVAL; - if ((flags & BRCMF_FW_REQUEST_NVRAM) && !nvram) + if (!brcmf_fw_request_is_valid(req)) return -EINVAL; fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL); @@ -541,26 +621,11 @@ int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, return -ENOMEM; fwctx->dev = dev; - fwctx->flags = flags; + fwctx->req = req; fwctx->done = fw_cb; - if (flags & BRCMF_FW_REQUEST_NVRAM) - fwctx->nvram_name = nvram; - fwctx->domain_nr = domain_nr; - fwctx->bus_nr = bus_nr; - - return request_firmware_nowait(THIS_MODULE, true, code, dev, - GFP_KERNEL, fwctx, - brcmf_fw_request_code_done); -} -int brcmf_fw_get_firmwares(struct device *dev, u16 flags, - const char *code, const char *nvram, - void (*fw_cb)(struct device *dev, int err, - const struct firmware *fw, - void *nvram_image, u32 nvram_len)) -{ - return brcmf_fw_get_firmwares_pcie(dev, flags, code, nvram, fw_cb, 0, - 0); + brcmf_fw_request_next_item(fwctx, true); + return 0; } static void brcmf_fw_get_full_name(char fw_name[BRCMF_FW_NAME_LEN], |