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_code_done(const struct firmware *fw, void *ctx) { struct brcmf_fw *fwctx = ctx; int ret; brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev)); if (!fw) goto fail; /* only requested code so done here */ if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) { fwctx->done(fwctx->dev, fw, NULL, 0); kfree(fwctx); return; } fwctx->code = fw; ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name, fwctx->dev, GFP_KERNEL, fwctx, brcmf_fw_request_nvram_done); if (!ret) return; brcmf_fw_request_nvram_done(NULL, fwctx); return; fail: brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); device_release_driver(fwctx->dev); kfree(fwctx); }
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; cur = &fwctx->req->items[fwctx->curpos]; brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path, fw ? "" : "not "); 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; 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: fwctx->done(fwctx->dev, ret, fwctx->req); kfree(fwctx); }