return IRQ_HANDLED;
 }
 
-static void bcm43xx_release_firmware(struct bcm43xx_private *bcm)
+static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force)
 {
-       if (bcm->firmware_norelease)
+       if (bcm->firmware_norelease && !force)
                return; /* Suspending or controller reset. */
        release_firmware(bcm->ucode);
        bcm->ucode = NULL;
 out:
        return err;
 error:
-       bcm43xx_release_firmware(bcm);
+       bcm43xx_release_firmware(bcm, 1);
        goto out;
 err_noinitval:
        printk(KERN_ERR PFX "Error: No InitVals available!\n");
 #endif
 }
 
-static void bcm43xx_write_initvals(struct bcm43xx_private *bcm,
-                                  const struct bcm43xx_initval *data,
-                                  const unsigned int len)
+static int bcm43xx_write_initvals(struct bcm43xx_private *bcm,
+                                 const struct bcm43xx_initval *data,
+                                 const unsigned int len)
 {
        u16 offset, size;
        u32 value;
                size = be16_to_cpu(data[i].size);
                value = be32_to_cpu(data[i].value);
 
-               if (size == 2)
-                       bcm43xx_write16(bcm, offset, value);
-               else if (size == 4)
+               if (unlikely(offset >= 0x1000))
+                       goto err_format;
+               if (size == 2) {
+                       if (unlikely(value & 0xFFFF0000))
+                               goto err_format;
+                       bcm43xx_write16(bcm, offset, (u16)value);
+               } else if (size == 4) {
                        bcm43xx_write32(bcm, offset, value);
-               else
-                       printk(KERN_ERR PFX "InitVals fileformat error.\n");
+               } else
+                       goto err_format;
        }
+
+       return 0;
+
+err_format:
+       printk(KERN_ERR PFX "InitVals (bcm43xx_initvalXX.fw) file-format error. "
+                           "Please fix your bcm43xx firmware files.\n");
+       return -EPROTO;
 }
 
-static void bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
+static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
 {
+       int err;
+
 #ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT
        bcm43xx_mmioprint_enable(bcm);
 #else
        bcm43xx_mmioprint_disable(bcm);
 #endif
 
-       bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data,
-                              bcm->initvals0->size / sizeof(struct bcm43xx_initval));
+       err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data,
+                                    bcm->initvals0->size / sizeof(struct bcm43xx_initval));
+       if (err)
+               goto out;
        if (bcm->initvals1) {
-               bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data,
-                                      bcm->initvals1->size / sizeof(struct bcm43xx_initval));
+               err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data,
+                                            bcm->initvals1->size / sizeof(struct bcm43xx_initval));
+               if (err)
+                       goto out;
        }
 
+out:
 #ifdef DEBUG_ENABLE_UCODE_MMIO_PRINT
        bcm43xx_mmioprint_disable(bcm);
 #else
        bcm43xx_mmioprint_enable(bcm);
 #endif
+       return err;
 }
 
 static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
                bcm43xx_leds_exit(bcm);
        bcm43xx_gpio_cleanup(bcm);
        free_irq(bcm->irq, bcm);
-       bcm43xx_release_firmware(bcm);
+       bcm43xx_release_firmware(bcm, 0);
 }
 
 /* Initialize the chip
 
        err = bcm43xx_initialize_irq(bcm);
        if (err)
-               goto out;
+               goto err_release_fw;
 
        err = bcm43xx_gpio_init(bcm);
        if (err)
                goto err_free_irq;
 
-       bcm43xx_upload_initvals(bcm);
+       err = bcm43xx_upload_initvals(bcm);
+       if (err)
+               goto err_gpio_cleanup;
        bcm43xx_radio_turn_on(bcm);
 
        if (modparam_noleds)
 
 err_radio_off:
        bcm43xx_radio_turn_off(bcm);
+err_gpio_cleanup:
        bcm43xx_gpio_cleanup(bcm);
 err_free_irq:
        free_irq(bcm->irq, bcm);
+err_release_fw:
+       bcm43xx_release_firmware(bcm, 1);
        goto out;
 }