|
@@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
|
|
|
b43warn(wl, text);
|
|
|
}
|
|
|
|
|
|
+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;
|
|
|
u32 size;
|
|
|
int err;
|
|
@@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
|
|
|
B43_WARN_ON(1);
|
|
|
return -ENOSYS;
|
|
|
}
|
|
|
- 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) {
|
|
|
snprintf(ctx->errors[ctx->req_type],
|
|
|
sizeof(ctx->errors[ctx->req_type]),
|
|
|
- "Firmware file \"%s\" not found\n", ctx->fwname);
|
|
|
+ "Firmware file \"%s\" not found\n",
|
|
|
+ ctx->fwname);
|
|
|
return err;
|
|
|
} else if (err) {
|
|
|
snprintf(ctx->errors[ctx->req_type],
|
|
@@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
|
|
|
ctx->fwname, err);
|
|
|
return err;
|
|
|
}
|
|
|
- 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) {
|
|
|
case B43_FW_TYPE_UCODE:
|
|
|
case B43_FW_TYPE_PCM:
|
|
|
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;
|
|
|
/* fallthrough */
|
|
|
case B43_FW_TYPE_IV:
|
|
@@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
|
|
|
goto err_format;
|
|
|
}
|
|
|
|
|
|
- fw->data = blob;
|
|
|
+ fw->data = ctx->blob;
|
|
|
fw->filename = name;
|
|
|
fw->type = ctx->req_type;
|
|
|
|
|
@@ -2172,7 +2200,7 @@ err_format:
|
|
|
snprintf(ctx->errors[ctx->req_type],
|
|
|
sizeof(ctx->errors[ctx->req_type]),
|
|
|
"Firmware file \"%s\" format error.\n", ctx->fwname);
|
|
|
- release_firmware(blob);
|
|
|
+ release_firmware(ctx->blob);
|
|
|
|
|
|
return -EPROTO;
|
|
|
}
|
|
@@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
|
|
|
goto err_no_ucode;
|
|
|
}
|
|
|
}
|
|
|
- err = b43_do_request_fw(ctx, filename, &fw->ucode);
|
|
|
+ err = b43_do_request_fw(ctx, filename, &fw->ucode, true);
|
|
|
if (err)
|
|
|
goto err_load;
|
|
|
|
|
@@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
|
|
|
else
|
|
|
goto err_no_pcm;
|
|
|
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) {
|
|
|
/* We did not find a PCM file? Not fatal, but
|
|
|
* core rev <= 10 must do without hwcrypto then. */
|
|
@@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
|
|
|
default:
|
|
|
goto err_no_initvals;
|
|
|
}
|
|
|
- err = b43_do_request_fw(ctx, filename, &fw->initvals);
|
|
|
+ err = b43_do_request_fw(ctx, filename, &fw->initvals, false);
|
|
|
if (err)
|
|
|
goto err_load;
|
|
|
|
|
@@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
|
|
|
default:
|
|
|
goto err_no_initvals;
|
|
|
}
|
|
|
- err = b43_do_request_fw(ctx, filename, &fw->initvals_band);
|
|
|
+ err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false);
|
|
|
if (err)
|
|
|
goto err_load;
|
|
|
|