Bluetooth: Use kzalloc for drivers
[pandora-kernel.git] / drivers / bluetooth / btmrvl_sdio.c
index df0773e..dcc2a6e 100644 (file)
@@ -47,6 +47,7 @@
  * module_exit function is called.
  */
 static u8 user_rmmod;
+static u8 sdio_ireg;
 
 static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
        .helper         = "sd8688_helper.bin",
@@ -83,10 +84,10 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
        *dat = 0;
 
        fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret);
+       if (ret)
+               return -EIO;
 
-       if (!ret)
-               fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
-
+       fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
        if (ret)
                return -EIO;
 
@@ -216,7 +217,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
 
        tmphlprbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
 
-       tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL);
+       tmphlprbuf = kzalloc(tmphlprbufsz, GFP_KERNEL);
        if (!tmphlprbuf) {
                BT_ERR("Unable to allocate buffer for helper."
                        " Terminating download");
@@ -224,8 +225,6 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
                goto done;
        }
 
-       memset(tmphlprbuf, 0, tmphlprbufsz);
-
        helperbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, BTSDIO_DMA_ALIGN);
 
        /* Perform helper data transfer */
@@ -318,7 +317,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
        BT_DBG("Downloading FW image (%d bytes)", firmwarelen);
 
        tmpfwbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
-       tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL);
+       tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
        if (!tmpfwbuf) {
                BT_ERR("Unable to allocate buffer for firmware."
                       " Terminating download");
@@ -326,8 +325,6 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
                goto done;
        }
 
-       memset(tmpfwbuf, 0, tmpfwbufsz);
-
        /* Ensure aligned firmware buffer */
        fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, BTSDIO_DMA_ALIGN);
 
@@ -555,78 +552,79 @@ exit:
        return ret;
 }
 
-static int btmrvl_sdio_get_int_status(struct btmrvl_private *priv, u8 * ireg)
+static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv)
 {
-       int ret;
-       u8 sdio_ireg = 0;
+       ulong flags;
+       u8 ireg;
        struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
 
-       *ireg = 0;
-
-       sdio_ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
-       if (ret) {
-               BT_ERR("sdio_readb: read int status register failed");
-               ret = -EIO;
-               goto done;
-       }
-
-       if (sdio_ireg != 0) {
-               /*
-                * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
-                * Clear the interrupt status register and re-enable the
-                * interrupt.
-                */
-               BT_DBG("sdio_ireg = 0x%x", sdio_ireg);
-
-               sdio_writeb(card->func, ~(sdio_ireg) & (DN_LD_HOST_INT_STATUS |
-                                                       UP_LD_HOST_INT_STATUS),
-                           HOST_INTSTATUS_REG, &ret);
-               if (ret) {
-                       BT_ERR("sdio_writeb: clear int status register "
-                               "failed");
-                       ret = -EIO;
-                       goto done;
-               }
-       }
+       spin_lock_irqsave(&priv->driver_lock, flags);
+       ireg = sdio_ireg;
+       sdio_ireg = 0;
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
 
-       if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
+       sdio_claim_host(card->func);
+       if (ireg & DN_LD_HOST_INT_STATUS) {
                if (priv->btmrvl_dev.tx_dnld_rdy)
                        BT_DBG("tx_done already received: "
-                               " int_status=0x%x", sdio_ireg);
+                               " int_status=0x%x", ireg);
                else
                        priv->btmrvl_dev.tx_dnld_rdy = true;
        }
 
-       if (sdio_ireg & UP_LD_HOST_INT_STATUS)
+       if (ireg & UP_LD_HOST_INT_STATUS)
                btmrvl_sdio_card_to_host(priv);
 
-       *ireg = sdio_ireg;
-
-       ret = 0;
+       sdio_release_host(card->func);
 
-done:
-       return ret;
+       return 0;
 }
 
 static void btmrvl_sdio_interrupt(struct sdio_func *func)
 {
        struct btmrvl_private *priv;
-       struct hci_dev *hcidev;
        struct btmrvl_sdio_card *card;
+       ulong flags;
        u8 ireg = 0;
+       int ret;
 
        card = sdio_get_drvdata(func);
-       if (card && card->priv) {
-               priv = card->priv;
-               hcidev = priv->btmrvl_dev.hcidev;
+       if (!card || !card->priv) {
+               BT_ERR("sbi_interrupt(%p) card or priv is "
+                               "NULL, card=%p\n", func, card);
+               return;
+       }
 
-               if (btmrvl_sdio_get_int_status(priv, &ireg))
-                       BT_ERR("reading HOST_INT_STATUS_REG failed");
-               else
-                       BT_DBG("HOST_INT_STATUS_REG %#x", ireg);
+       priv = card->priv;
+
+       ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
+       if (ret) {
+               BT_ERR("sdio_readb: read int status register failed");
+               return;
+       }
+
+       if (ireg != 0) {
+               /*
+                * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
+                * Clear the interrupt status register and re-enable the
+                * interrupt.
+                */
+               BT_DBG("ireg = 0x%x", ireg);
 
-               btmrvl_interrupt(priv);
+               sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
+                                       UP_LD_HOST_INT_STATUS),
+                               HOST_INTSTATUS_REG, &ret);
+               if (ret) {
+                       BT_ERR("sdio_writeb: clear int status register failed");
+                       return;
+               }
        }
+
+       spin_lock_irqsave(&priv->driver_lock, flags);
+       sdio_ireg |= ireg;
+       spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+       btmrvl_interrupt(priv);
 }
 
 static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
@@ -930,6 +928,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
        /* Initialize the interface specific function pointers */
        priv->hw_host_to_card = btmrvl_sdio_host_to_card;
        priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
+       priv->hw_process_int_status = btmrvl_sdio_process_int_status;
 
        if (btmrvl_register_hdev(priv)) {
                BT_ERR("Register hdev failed!");