diff options
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r-- | drivers/net/wireless/b43/main.c | 54 |
1 files changed, 41 insertions, 13 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 16ab280359bd..806e34c19281 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2090,7 +2090,14 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) +static void b43_fw_cb(const struct firmware *firmware, void *context) +{ + struct b43_request_fw_context *ctx = context; + + ctx->blob = firmware; + complete(&ctx->fw_load_complete); +} + int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, - struct b43_firmware_file *fw) + struct b43_firmware_file *fw, bool async) { - const struct firmware *blob; struct b43_fw_header *hdr; @@ -2133,3 +2140,22 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, } - err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); + if (async) { + /* do this part asynchronously */ + init_completion(&ctx->fw_load_complete); + err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, + ctx->dev->dev->dev, GFP_KERNEL, + ctx, b43_fw_cb); + if (err < 0) { + pr_err("Unable to load firmware\n"); + return err; + } + /* stall here until fw ready */ + wait_for_completion(&ctx->fw_load_complete); + if (ctx->blob) + goto fw_ready; + /* On some ARM systems, the async request will fail, but the next sync + * request works. For this reason, we dall through here + */ + } + err = request_firmware(&ctx->blob, ctx->fwname, + ctx->dev->dev->dev); if (err == -ENOENT) { @@ -2137,3 +2163,4 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, sizeof(ctx->errors[ctx->req_type]), - "Firmware file \"%s\" not found\n", ctx->fwname); + "Firmware file \"%s\" not found\n", + ctx->fwname); return err; @@ -2146,5 +2173,6 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, } - if (blob->size < sizeof(struct b43_fw_header)) +fw_ready: + if (ctx->blob->size < sizeof(struct b43_fw_header)) goto err_format; - hdr = (struct b43_fw_header *)(blob->data); + hdr = (struct b43_fw_header *)(ctx->blob->data); switch (hdr->type) { @@ -2153,3 +2181,3 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, size = be32_to_cpu(hdr->size); - if (size != blob->size - sizeof(struct b43_fw_header)) + if (size != ctx->blob->size - sizeof(struct b43_fw_header)) goto err_format; @@ -2164,3 +2192,3 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, - fw->data = blob; + fw->data = ctx->blob; fw->filename = name; @@ -2174,3 +2202,3 @@ err_format: "Firmware file \"%s\" format error.\n", ctx->fwname); - release_firmware(blob); + release_firmware(ctx->blob); @@ -2225,3 +2253,3 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) } - err = b43_do_request_fw(ctx, filename, &fw->ucode); + err = b43_do_request_fw(ctx, filename, &fw->ucode, true); if (err) @@ -2237,3 +2265,3 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) fw->pcm_request_failed = false; - err = b43_do_request_fw(ctx, filename, &fw->pcm); + err = b43_do_request_fw(ctx, filename, &fw->pcm, false); if (err == -ENOENT) { @@ -2298,3 +2326,3 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) } - err = b43_do_request_fw(ctx, filename, &fw->initvals); + err = b43_do_request_fw(ctx, filename, &fw->initvals, false); if (err) @@ -2357,3 +2385,3 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) } - err = b43_do_request_fw(ctx, filename, &fw->initvals_band); + err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); if (err) |