b43: Fix unload oops if firmware is not available
The asyncronous firmware load uses a completion struct to hold firmware processing until the user-space routines are up and running. There is. however, a problem in that the waiter is nevered canceled during teardown. As a result, unloading the driver when firmware is not available causes an oops. To be able to access the completion structure at teardown, it had to be moved into the b43_wldev structure. This patch also fixes a typo in a comment. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Cc: Stable <stable@vger.kernel.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
09164043f6
commit
0673effd41
|
@ -731,8 +731,6 @@ enum b43_firmware_file_type {
|
||||||
struct b43_request_fw_context {
|
struct b43_request_fw_context {
|
||||||
/* The device we are requesting the fw for. */
|
/* The device we are requesting the fw for. */
|
||||||
struct b43_wldev *dev;
|
struct b43_wldev *dev;
|
||||||
/* a completion event structure needed if this call is asynchronous */
|
|
||||||
struct completion fw_load_complete;
|
|
||||||
/* a pointer to the firmware object */
|
/* a pointer to the firmware object */
|
||||||
const struct firmware *blob;
|
const struct firmware *blob;
|
||||||
/* The type of firmware to request. */
|
/* The type of firmware to request. */
|
||||||
|
@ -809,6 +807,8 @@ enum {
|
||||||
struct b43_wldev {
|
struct b43_wldev {
|
||||||
struct b43_bus_dev *dev;
|
struct b43_bus_dev *dev;
|
||||||
struct b43_wl *wl;
|
struct b43_wl *wl;
|
||||||
|
/* a completion event structure needed if this call is asynchronous */
|
||||||
|
struct completion fw_load_complete;
|
||||||
|
|
||||||
/* The device initialization status.
|
/* The device initialization status.
|
||||||
* Use b43_status() to query. */
|
* Use b43_status() to query. */
|
||||||
|
|
|
@ -2070,6 +2070,7 @@ void b43_do_release_fw(struct b43_firmware_file *fw)
|
||||||
|
|
||||||
static void b43_release_firmware(struct b43_wldev *dev)
|
static void b43_release_firmware(struct b43_wldev *dev)
|
||||||
{
|
{
|
||||||
|
complete(&dev->fw_load_complete);
|
||||||
b43_do_release_fw(&dev->fw.ucode);
|
b43_do_release_fw(&dev->fw.ucode);
|
||||||
b43_do_release_fw(&dev->fw.pcm);
|
b43_do_release_fw(&dev->fw.pcm);
|
||||||
b43_do_release_fw(&dev->fw.initvals);
|
b43_do_release_fw(&dev->fw.initvals);
|
||||||
|
@ -2095,7 +2096,7 @@ static void b43_fw_cb(const struct firmware *firmware, void *context)
|
||||||
struct b43_request_fw_context *ctx = context;
|
struct b43_request_fw_context *ctx = context;
|
||||||
|
|
||||||
ctx->blob = firmware;
|
ctx->blob = firmware;
|
||||||
complete(&ctx->fw_load_complete);
|
complete(&ctx->dev->fw_load_complete);
|
||||||
}
|
}
|
||||||
|
|
||||||
int b43_do_request_fw(struct b43_request_fw_context *ctx,
|
int b43_do_request_fw(struct b43_request_fw_context *ctx,
|
||||||
|
@ -2142,7 +2143,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
|
||||||
}
|
}
|
||||||
if (async) {
|
if (async) {
|
||||||
/* do this part asynchronously */
|
/* do this part asynchronously */
|
||||||
init_completion(&ctx->fw_load_complete);
|
init_completion(&ctx->dev->fw_load_complete);
|
||||||
err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname,
|
err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname,
|
||||||
ctx->dev->dev->dev, GFP_KERNEL,
|
ctx->dev->dev->dev, GFP_KERNEL,
|
||||||
ctx, b43_fw_cb);
|
ctx, b43_fw_cb);
|
||||||
|
@ -2150,12 +2151,11 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
|
||||||
pr_err("Unable to load firmware\n");
|
pr_err("Unable to load firmware\n");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
/* stall here until fw ready */
|
wait_for_completion(&ctx->dev->fw_load_complete);
|
||||||
wait_for_completion(&ctx->fw_load_complete);
|
|
||||||
if (ctx->blob)
|
if (ctx->blob)
|
||||||
goto fw_ready;
|
goto fw_ready;
|
||||||
/* On some ARM systems, the async request will fail, but the next sync
|
/* On some ARM systems, the async request will fail, but the next sync
|
||||||
* request works. For this reason, we dall through here
|
* request works. For this reason, we fall through here
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
err = request_firmware(&ctx->blob, ctx->fwname,
|
err = request_firmware(&ctx->blob, ctx->fwname,
|
||||||
|
|
Loading…
Reference in New Issue