diff options
-rw-r--r-- | drivers/bluetooth/btmrvl_drv.h | 1 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_main.c | 5 | ||||
-rw-r--r-- | drivers/bluetooth/btmrvl_sdio.c | 97 |
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 | */ |
49 | static u8 user_rmmod; | 49 | static u8 user_rmmod; |
50 | static u8 sdio_ireg; | ||
50 | 51 | ||
51 | static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = { | 52 | static 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 | ||
558 | static int btmrvl_sdio_get_int_status(struct btmrvl_private *priv, u8 * ireg) | 559 | static 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 | ||
607 | done: | 584 | return 0; |
608 | return ret; | ||
609 | } | 585 | } |
610 | 586 | ||
611 | static void btmrvl_sdio_interrupt(struct sdio_func *func) | 587 | static 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 | ||
632 | static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card) | 634 | static 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!"); |