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 | ||
