diff options
Diffstat (limited to 'drivers/net/wireless/b43')
| -rw-r--r-- | drivers/net/wireless/b43/b43.h | 5 | ||||
| -rw-r--r-- | drivers/net/wireless/b43/main.c | 54 | ||||
| -rw-r--r-- | drivers/net/wireless/b43/main.h | 5 |
3 files changed, 48 insertions, 16 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index b298e5d68be2..10e288d470e7 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <linux/hw_random.h> | 7 | #include <linux/hw_random.h> |
| 8 | #include <linux/bcma/bcma.h> | 8 | #include <linux/bcma/bcma.h> |
| 9 | #include <linux/ssb/ssb.h> | 9 | #include <linux/ssb/ssb.h> |
| 10 | #include <linux/completion.h> | ||
| 10 | #include <net/mac80211.h> | 11 | #include <net/mac80211.h> |
| 11 | 12 | ||
| 12 | #include "debugfs.h" | 13 | #include "debugfs.h" |
| @@ -722,6 +723,10 @@ enum b43_firmware_file_type { | |||
| 722 | struct b43_request_fw_context { | 723 | struct b43_request_fw_context { |
| 723 | /* The device we are requesting the fw for. */ | 724 | /* The device we are requesting the fw for. */ |
| 724 | struct b43_wldev *dev; | 725 | struct b43_wldev *dev; |
| 726 | /* a completion event structure needed if this call is asynchronous */ | ||
| 727 | struct completion fw_load_complete; | ||
| 728 | /* a pointer to the firmware object */ | ||
| 729 | const struct firmware *blob; | ||
| 725 | /* The type of firmware to request. */ | 730 | /* The type of firmware to request. */ |
| 726 | enum b43_firmware_file_type req_type; | 731 | enum b43_firmware_file_type req_type; |
| 727 | /* Error messages for each firmware type. */ | 732 | /* Error messages for each firmware type. */ |
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 | ||
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 8c684cd33529..abac25ee958d 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h | |||
| @@ -137,9 +137,8 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); | |||
| 137 | 137 | ||
| 138 | 138 | ||
| 139 | struct b43_request_fw_context; | 139 | struct b43_request_fw_context; |
| 140 | int b43_do_request_fw(struct b43_request_fw_context *ctx, | 140 | int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, |
| 141 | const char *name, | 141 | struct b43_firmware_file *fw, bool async); |
| 142 | struct b43_firmware_file *fw); | ||
| 143 | void b43_do_release_fw(struct b43_firmware_file *fw); | 142 | void b43_do_release_fw(struct b43_firmware_file *fw); |
| 144 | 143 | ||
| 145 | #endif /* B43_MAIN_H_ */ | 144 | #endif /* B43_MAIN_H_ */ |
