Bluetooth: btmrvl: release lock while waiting for fw download complete
authorAndreas Fenkart <andreas.fenkart@streamunlimited.com>
Mon, 22 Apr 2013 09:10:22 +0000 (11:10 +0200)
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>
Tue, 23 Apr 2013 23:55:51 +0000 (20:55 -0300)
If not winner, driver must release the sdio host lock, so the fw
download can progress. While holding the lock fw download is stalled
and the following error is produced:

[  235.746015] Bluetooth: FW failed to be active in time!
[  235.752799] Bluetooth: Downloading firmware failed!

Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
drivers/bluetooth/btmrvl_sdio.c

index 0e9e8e95916d29cc66b317ca1ad1baa8ea74d5cf..758d5ac81ecc19127990f8d49323ace1754e8d42 100644 (file)
@@ -234,7 +234,10 @@ static int btmrvl_sdio_verify_fw_download(struct btmrvl_sdio_card *card,
 
         /* Wait for firmware to become ready */
        for (tries = 0; tries < pollnum; tries++) {
-               if (btmrvl_sdio_read_fw_status(card, &firmwarestat) < 0)
+               sdio_claim_host(card->func);
+               ret = btmrvl_sdio_read_fw_status(card, &firmwarestat);
+               sdio_release_host(card->func);
+               if (ret < 0)
                        continue;
 
                if (firmwarestat == FIRMWARE_READY) {
@@ -882,13 +885,14 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
                BT_ERR("card or function is NULL!");
                return -EINVAL;
        }
-       sdio_claim_host(card->func);
 
        if (!btmrvl_sdio_verify_fw_download(card, 1)) {
                BT_DBG("Firmware already downloaded!");
-               goto done;
+               return 0;
        }
 
+       sdio_claim_host(card->func);
+
        /* Check if other function driver is downloading the firmware */
        fws0 = sdio_readb(card->func, card->reg->card_fw_status0, &ret);
        if (ret) {
@@ -918,15 +922,17 @@ static int btmrvl_sdio_download_fw(struct btmrvl_sdio_card *card)
                }
        }
 
+       sdio_release_host(card->func);
+
        if (btmrvl_sdio_verify_fw_download(card, pollnum)) {
                BT_ERR("FW failed to be active in time!");
-               ret = -ETIMEDOUT;
-               goto done;
+               return -ETIMEDOUT;
        }
 
+       return 0;
+
 done:
        sdio_release_host(card->func);
-
        return ret;
 }