aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2014-01-12 16:11:38 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-02-06 14:08:14 -0500
commit1a712907b90a5aad689e8757616537a506ba07f9 (patch)
treef547cd3d6233da33bf8a98f8362f0ed9ee4dd149
parenteeb405fd975fd5b684248d2d9039d685d34fac52 (diff)
b43: Fix unload oops if firmware is not available
commit 0673effd41dba323d6a280ef37b5ef29f3f5a653 upstream. 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> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/wireless/b43/b43.h4
-rw-r--r--drivers/net/wireless/b43/main.c10
2 files changed, 7 insertions, 7 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 7f3d461f7e8d..54376fddfaf9 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -731,8 +731,6 @@ enum b43_firmware_file_type {
731struct b43_request_fw_context { 731struct b43_request_fw_context {
732 /* The device we are requesting the fw for. */ 732 /* The device we are requesting the fw for. */
733 struct b43_wldev *dev; 733 struct b43_wldev *dev;
734 /* a completion event structure needed if this call is asynchronous */
735 struct completion fw_load_complete;
736 /* a pointer to the firmware object */ 734 /* a pointer to the firmware object */
737 const struct firmware *blob; 735 const struct firmware *blob;
738 /* The type of firmware to request. */ 736 /* The type of firmware to request. */
@@ -809,6 +807,8 @@ enum {
809struct b43_wldev { 807struct b43_wldev {
810 struct b43_bus_dev *dev; 808 struct b43_bus_dev *dev;
811 struct b43_wl *wl; 809 struct b43_wl *wl;
810 /* a completion event structure needed if this call is asynchronous */
811 struct completion fw_load_complete;
812 812
813 /* The device initialization status. 813 /* The device initialization status.
814 * Use b43_status() to query. */ 814 * Use b43_status() to query. */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 291a1199df96..0b7edd36cfa2 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2068,6 +2068,7 @@ void b43_do_release_fw(struct b43_firmware_file *fw)
2068 2068
2069static void b43_release_firmware(struct b43_wldev *dev) 2069static void b43_release_firmware(struct b43_wldev *dev)
2070{ 2070{
2071 complete(&dev->fw_load_complete);
2071 b43_do_release_fw(&dev->fw.ucode); 2072 b43_do_release_fw(&dev->fw.ucode);
2072 b43_do_release_fw(&dev->fw.pcm); 2073 b43_do_release_fw(&dev->fw.pcm);
2073 b43_do_release_fw(&dev->fw.initvals); 2074 b43_do_release_fw(&dev->fw.initvals);
@@ -2093,7 +2094,7 @@ static void b43_fw_cb(const struct firmware *firmware, void *context)
2093 struct b43_request_fw_context *ctx = context; 2094 struct b43_request_fw_context *ctx = context;
2094 2095
2095 ctx->blob = firmware; 2096 ctx->blob = firmware;
2096 complete(&ctx->fw_load_complete); 2097 complete(&ctx->dev->fw_load_complete);
2097} 2098}
2098 2099
2099int b43_do_request_fw(struct b43_request_fw_context *ctx, 2100int b43_do_request_fw(struct b43_request_fw_context *ctx,
@@ -2140,7 +2141,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
2140 } 2141 }
2141 if (async) { 2142 if (async) {
2142 /* do this part asynchronously */ 2143 /* do this part asynchronously */
2143 init_completion(&ctx->fw_load_complete); 2144 init_completion(&ctx->dev->fw_load_complete);
2144 err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, 2145 err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname,
2145 ctx->dev->dev->dev, GFP_KERNEL, 2146 ctx->dev->dev->dev, GFP_KERNEL,
2146 ctx, b43_fw_cb); 2147 ctx, b43_fw_cb);
@@ -2148,12 +2149,11 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
2148 pr_err("Unable to load firmware\n"); 2149 pr_err("Unable to load firmware\n");
2149 return err; 2150 return err;
2150 } 2151 }
2151 /* stall here until fw ready */ 2152 wait_for_completion(&ctx->dev->fw_load_complete);
2152 wait_for_completion(&ctx->fw_load_complete);
2153 if (ctx->blob) 2153 if (ctx->blob)
2154 goto fw_ready; 2154 goto fw_ready;
2155 /* On some ARM systems, the async request will fail, but the next sync 2155 /* On some ARM systems, the async request will fail, but the next sync
2156 * request works. For this reason, we dall through here 2156 * request works. For this reason, we fall through here
2157 */ 2157 */
2158 } 2158 }
2159 err = request_firmware(&ctx->blob, ctx->fwname, 2159 err = request_firmware(&ctx->blob, ctx->fwname,