aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/bluetooth/btmrvl_drv.h1
-rw-r--r--drivers/bluetooth/btmrvl_main.c5
-rw-r--r--drivers/bluetooth/btmrvl_sdio.c97
3 files changed, 55 insertions, 48 deletions
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index bed0ba630235..872cb6cfcd0d 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -76,6 +76,7 @@ struct btmrvl_private {
76 int (*hw_host_to_card) (struct btmrvl_private *priv, 76 int (*hw_host_to_card) (struct btmrvl_private *priv,
77 u8 *payload, u16 nb); 77 u8 *payload, u16 nb);
78 int (*hw_wakeup_firmware) (struct btmrvl_private *priv); 78 int (*hw_wakeup_firmware) (struct btmrvl_private *priv);
79 int (*hw_process_int_status) (struct btmrvl_private *priv);
79 spinlock_t driver_lock; /* spinlock used by driver */ 80 spinlock_t driver_lock; /* spinlock used by driver */
80#ifdef CONFIG_DEBUG_FS 81#ifdef CONFIG_DEBUG_FS
81 void *debugfs_data; 82 void *debugfs_data;
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index ee37ef0caee2..0d32ec82e9bf 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -502,14 +502,17 @@ static int btmrvl_service_main_thread(void *data)
502 spin_lock_irqsave(&priv->driver_lock, flags); 502 spin_lock_irqsave(&priv->driver_lock, flags);
503 if (adapter->int_count) { 503 if (adapter->int_count) {
504 adapter->int_count = 0; 504 adapter->int_count = 0;
505 spin_unlock_irqrestore(&priv->driver_lock, flags);
506 priv->hw_process_int_status(priv);
505 } else if (adapter->ps_state == PS_SLEEP && 507 } else if (adapter->ps_state == PS_SLEEP &&
506 !skb_queue_empty(&adapter->tx_queue)) { 508 !skb_queue_empty(&adapter->tx_queue)) {
507 spin_unlock_irqrestore(&priv->driver_lock, flags); 509 spin_unlock_irqrestore(&priv->driver_lock, flags);
508 adapter->wakeup_tries++; 510 adapter->wakeup_tries++;
509 priv->hw_wakeup_firmware(priv); 511 priv->hw_wakeup_firmware(priv);
510 continue; 512 continue;
513 } else {
514 spin_unlock_irqrestore(&priv->driver_lock, flags);
511 } 515 }
512 spin_unlock_irqrestore(&priv->driver_lock, flags);
513 516
514 if (adapter->ps_state == PS_SLEEP) 517 if (adapter->ps_state == PS_SLEEP)
515 continue; 518 continue;
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 47f0f917dec9..182e55345d6a 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -47,6 +47,7 @@
47 * module_exit function is called. 47 * module_exit function is called.
48 */ 48 */
49static u8 user_rmmod; 49static u8 user_rmmod;
50static u8 sdio_ireg;
50 51
51static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = { 52static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
52 .helper = "sd8688_helper.bin", 53 .helper = "sd8688_helper.bin",
@@ -555,78 +556,79 @@ exit:
555 return ret; 556 return ret;
556} 557}
557 558
558static int btmrvl_sdio_get_int_status(struct btmrvl_private *priv, u8 * ireg) 559static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv)
559{ 560{
560 int ret; 561 ulong flags;
561 u8 sdio_ireg = 0; 562 u8 ireg;
562 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; 563 struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
563 564
564 *ireg = 0; 565 spin_lock_irqsave(&priv->driver_lock, flags);
565 566 ireg = sdio_ireg;
566 sdio_ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret); 567 sdio_ireg = 0;
567 if (ret) { 568 spin_unlock_irqrestore(&priv->driver_lock, flags);
568 BT_ERR("sdio_readb: read int status register failed");
569 ret = -EIO;
570 goto done;
571 }
572
573 if (sdio_ireg != 0) {
574 /*
575 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
576 * Clear the interrupt status register and re-enable the
577 * interrupt.
578 */
579 BT_DBG("sdio_ireg = 0x%x", sdio_ireg);
580
581 sdio_writeb(card->func, ~(sdio_ireg) & (DN_LD_HOST_INT_STATUS |
582 UP_LD_HOST_INT_STATUS),
583 HOST_INTSTATUS_REG, &ret);
584 if (ret) {
585 BT_ERR("sdio_writeb: clear int status register "
586 "failed");
587 ret = -EIO;
588 goto done;
589 }
590 }
591 569
592 if (sdio_ireg & DN_LD_HOST_INT_STATUS) { 570 sdio_claim_host(card->func);
571 if (ireg & DN_LD_HOST_INT_STATUS) {
593 if (priv->btmrvl_dev.tx_dnld_rdy) 572 if (priv->btmrvl_dev.tx_dnld_rdy)
594 BT_DBG("tx_done already received: " 573 BT_DBG("tx_done already received: "
595 " int_status=0x%x", sdio_ireg); 574 " int_status=0x%x", ireg);
596 else 575 else
597 priv->btmrvl_dev.tx_dnld_rdy = true; 576 priv->btmrvl_dev.tx_dnld_rdy = true;
598 } 577 }
599 578
600 if (sdio_ireg & UP_LD_HOST_INT_STATUS) 579 if (ireg & UP_LD_HOST_INT_STATUS)
601 btmrvl_sdio_card_to_host(priv); 580 btmrvl_sdio_card_to_host(priv);
602 581
603 *ireg = sdio_ireg; 582 sdio_release_host(card->func);
604
605 ret = 0;
606 583
607done: 584 return 0;
608 return ret;
609} 585}
610 586
611static void btmrvl_sdio_interrupt(struct sdio_func *func) 587static void btmrvl_sdio_interrupt(struct sdio_func *func)
612{ 588{
613 struct btmrvl_private *priv; 589 struct btmrvl_private *priv;
614 struct hci_dev *hcidev;
615 struct btmrvl_sdio_card *card; 590 struct btmrvl_sdio_card *card;
591 ulong flags;
616 u8 ireg = 0; 592 u8 ireg = 0;
593 int ret;
617 594
618 card = sdio_get_drvdata(func); 595 card = sdio_get_drvdata(func);
619 if (card && card->priv) { 596 if (!card || !card->priv) {
620 priv = card->priv; 597 BT_ERR("sbi_interrupt(%p) card or priv is "
621 hcidev = priv->btmrvl_dev.hcidev; 598 "NULL, card=%p\n", func, card);
599 return;
600 }
622 601
623 if (btmrvl_sdio_get_int_status(priv, &ireg)) 602 priv = card->priv;
624 BT_ERR("reading HOST_INT_STATUS_REG failed");
625 else
626 BT_DBG("HOST_INT_STATUS_REG %#x", ireg);
627 603
628 btmrvl_interrupt(priv); 604 ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
605 if (ret) {
606 BT_ERR("sdio_readb: read int status register failed");
607 return;
629 } 608 }
609
610 if (ireg != 0) {
611 /*
612 * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
613 * Clear the interrupt status register and re-enable the
614 * interrupt.
615 */
616 BT_DBG("ireg = 0x%x", ireg);
617
618 sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
619 UP_LD_HOST_INT_STATUS),
620 HOST_INTSTATUS_REG, &ret);
621 if (ret) {
622 BT_ERR("sdio_writeb: clear int status register failed");
623 return;
624 }
625 }
626
627 spin_lock_irqsave(&priv->driver_lock, flags);
628 sdio_ireg |= ireg;
629 spin_unlock_irqrestore(&priv->driver_lock, flags);
630
631 btmrvl_interrupt(priv);
630} 632}
631 633
632static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card) 634static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
@@ -930,6 +932,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
930 /* Initialize the interface specific function pointers */ 932 /* Initialize the interface specific function pointers */
931 priv->hw_host_to_card = btmrvl_sdio_host_to_card; 933 priv->hw_host_to_card = btmrvl_sdio_host_to_card;
932 priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw; 934 priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
935 priv->hw_process_int_status = btmrvl_sdio_process_int_status;
933 936
934 if (btmrvl_register_hdev(priv)) { 937 if (btmrvl_register_hdev(priv)) {
935 BT_ERR("Register hdev failed!"); 938 BT_ERR("Register hdev failed!");