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 | |||
@@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) | |||
2088 | b43warn(wl, text); | 2088 | b43warn(wl, text); |
2089 | } | 2089 | } |
2090 | 2090 | ||
2091 | static void b43_fw_cb(const struct firmware *firmware, void *context) | ||
2092 | { | ||
2093 | struct b43_request_fw_context *ctx = context; | ||
2094 | |||
2095 | ctx->blob = firmware; | ||
2096 | complete(&ctx->fw_load_complete); | ||
2097 | } | ||
2098 | |||
2091 | int b43_do_request_fw(struct b43_request_fw_context *ctx, | 2099 | int b43_do_request_fw(struct b43_request_fw_context *ctx, |
2092 | const char *name, | 2100 | const char *name, |
2093 | struct b43_firmware_file *fw) | 2101 | struct b43_firmware_file *fw, bool async) |
2094 | { | 2102 | { |
2095 | const struct firmware *blob; | ||
2096 | struct b43_fw_header *hdr; | 2103 | struct b43_fw_header *hdr; |
2097 | u32 size; | 2104 | u32 size; |
2098 | int err; | 2105 | int err; |
@@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, | |||
2131 | B43_WARN_ON(1); | 2138 | B43_WARN_ON(1); |
2132 | return -ENOSYS; | 2139 | return -ENOSYS; |
2133 | } | 2140 | } |
2134 | err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); | 2141 | if (async) { |
2142 | /* do this part asynchronously */ | ||
2143 | init_completion(&ctx->fw_load_complete); | ||
2144 | err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, | ||
2145 | ctx->dev->dev->dev, GFP_KERNEL, | ||
2146 | ctx, b43_fw_cb); | ||
2147 | if (err < 0) { | ||
2148 | pr_err("Unable to load firmware\n"); | ||
2149 | return err; | ||
2150 | } | ||
2151 | /* stall here until fw ready */ | ||
2152 | wait_for_completion(&ctx->fw_load_complete); | ||
2153 | if (ctx->blob) | ||
2154 | goto fw_ready; | ||
2155 | /* On some ARM systems, the async request will fail, but the next sync | ||
2156 | * request works. For this reason, we dall through here | ||
2157 | */ | ||
2158 | } | ||
2159 | err = request_firmware(&ctx->blob, ctx->fwname, | ||
2160 | ctx->dev->dev->dev); | ||
2135 | if (err == -ENOENT) { | 2161 | if (err == -ENOENT) { |
2136 | snprintf(ctx->errors[ctx->req_type], | 2162 | snprintf(ctx->errors[ctx->req_type], |
2137 | sizeof(ctx->errors[ctx->req_type]), | 2163 | sizeof(ctx->errors[ctx->req_type]), |
2138 | "Firmware file \"%s\" not found\n", ctx->fwname); | 2164 | "Firmware file \"%s\" not found\n", |
2165 | ctx->fwname); | ||
2139 | return err; | 2166 | return err; |
2140 | } else if (err) { | 2167 | } else if (err) { |
2141 | snprintf(ctx->errors[ctx->req_type], | 2168 | snprintf(ctx->errors[ctx->req_type], |
@@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, | |||
2144 | ctx->fwname, err); | 2171 | ctx->fwname, err); |
2145 | return err; | 2172 | return err; |
2146 | } | 2173 | } |
2147 | if (blob->size < sizeof(struct b43_fw_header)) | 2174 | fw_ready: |
2175 | if (ctx->blob->size < sizeof(struct b43_fw_header)) | ||
2148 | goto err_format; | 2176 | goto err_format; |
2149 | hdr = (struct b43_fw_header *)(blob->data); | 2177 | hdr = (struct b43_fw_header *)(ctx->blob->data); |
2150 | switch (hdr->type) { | 2178 | switch (hdr->type) { |
2151 | case B43_FW_TYPE_UCODE: | 2179 | case B43_FW_TYPE_UCODE: |
2152 | case B43_FW_TYPE_PCM: | 2180 | case B43_FW_TYPE_PCM: |
2153 | size = be32_to_cpu(hdr->size); | 2181 | size = be32_to_cpu(hdr->size); |
2154 | if (size != blob->size - sizeof(struct b43_fw_header)) | 2182 | if (size != ctx->blob->size - sizeof(struct b43_fw_header)) |
2155 | goto err_format; | 2183 | goto err_format; |
2156 | /* fallthrough */ | 2184 | /* fallthrough */ |
2157 | case B43_FW_TYPE_IV: | 2185 | case B43_FW_TYPE_IV: |
@@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, | |||
2162 | goto err_format; | 2190 | goto err_format; |
2163 | } | 2191 | } |
2164 | 2192 | ||
2165 | fw->data = blob; | 2193 | fw->data = ctx->blob; |
2166 | fw->filename = name; | 2194 | fw->filename = name; |
2167 | fw->type = ctx->req_type; | 2195 | fw->type = ctx->req_type; |
2168 | 2196 | ||
@@ -2172,7 +2200,7 @@ err_format: | |||
2172 | snprintf(ctx->errors[ctx->req_type], | 2200 | snprintf(ctx->errors[ctx->req_type], |
2173 | sizeof(ctx->errors[ctx->req_type]), | 2201 | sizeof(ctx->errors[ctx->req_type]), |
2174 | "Firmware file \"%s\" format error.\n", ctx->fwname); | 2202 | "Firmware file \"%s\" format error.\n", ctx->fwname); |
2175 | release_firmware(blob); | 2203 | release_firmware(ctx->blob); |
2176 | 2204 | ||
2177 | return -EPROTO; | 2205 | return -EPROTO; |
2178 | } | 2206 | } |
@@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2223 | goto err_no_ucode; | 2251 | goto err_no_ucode; |
2224 | } | 2252 | } |
2225 | } | 2253 | } |
2226 | err = b43_do_request_fw(ctx, filename, &fw->ucode); | 2254 | err = b43_do_request_fw(ctx, filename, &fw->ucode, true); |
2227 | if (err) | 2255 | if (err) |
2228 | goto err_load; | 2256 | goto err_load; |
2229 | 2257 | ||
@@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2235 | else | 2263 | else |
2236 | goto err_no_pcm; | 2264 | goto err_no_pcm; |
2237 | fw->pcm_request_failed = false; | 2265 | fw->pcm_request_failed = false; |
2238 | err = b43_do_request_fw(ctx, filename, &fw->pcm); | 2266 | err = b43_do_request_fw(ctx, filename, &fw->pcm, false); |
2239 | if (err == -ENOENT) { | 2267 | if (err == -ENOENT) { |
2240 | /* We did not find a PCM file? Not fatal, but | 2268 | /* We did not find a PCM file? Not fatal, but |
2241 | * core rev <= 10 must do without hwcrypto then. */ | 2269 | * core rev <= 10 must do without hwcrypto then. */ |
@@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2296 | default: | 2324 | default: |
2297 | goto err_no_initvals; | 2325 | goto err_no_initvals; |
2298 | } | 2326 | } |
2299 | err = b43_do_request_fw(ctx, filename, &fw->initvals); | 2327 | err = b43_do_request_fw(ctx, filename, &fw->initvals, false); |
2300 | if (err) | 2328 | if (err) |
2301 | goto err_load; | 2329 | goto err_load; |
2302 | 2330 | ||
@@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2355 | default: | 2383 | default: |
2356 | goto err_no_initvals; | 2384 | goto err_no_initvals; |
2357 | } | 2385 | } |
2358 | err = b43_do_request_fw(ctx, filename, &fw->initvals_band); | 2386 | err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); |
2359 | if (err) | 2387 | if (err) |
2360 | goto err_load; | 2388 | goto err_load; |
2361 | 2389 | ||