diff options
author | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-10-30 15:15:57 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-11-11 05:58:58 -0500 |
commit | 32a07e4448f78158a75f7c1f0056289647d83946 (patch) | |
tree | c248329a3c55b151c09bce26c0aa2556e31c8f30 /drivers/net/wireless/ath/ath6kl/sdio.c | |
parent | cd4b8b85800a47dc68b9282ffc3a88b82e77f242 (diff) |
ath6kl: create ath6kl_hif_stop()
This is to reset hif layer for powering down hw.
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/sdio.c')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/sdio.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 56f83c40b8d8..2d155570bb5c 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
@@ -45,6 +45,8 @@ struct ath6kl_sdio { | |||
45 | struct list_head scat_req; | 45 | struct list_head scat_req; |
46 | 46 | ||
47 | spinlock_t scat_lock; | 47 | spinlock_t scat_lock; |
48 | bool scatter_enabled; | ||
49 | |||
48 | bool is_disabled; | 50 | bool is_disabled; |
49 | atomic_t irq_handling; | 51 | atomic_t irq_handling; |
50 | const struct sdio_device_id *id; | 52 | const struct sdio_device_id *id; |
@@ -651,6 +653,11 @@ static void ath6kl_sdio_cleanup_scatter(struct ath6kl *ar) | |||
651 | list_del(&s_req->list); | 653 | list_del(&s_req->list); |
652 | spin_unlock_bh(&ar_sdio->scat_lock); | 654 | spin_unlock_bh(&ar_sdio->scat_lock); |
653 | 655 | ||
656 | /* | ||
657 | * FIXME: should we also call completion handler with | ||
658 | * ath6kl_hif_rw_comp_handler() with status -ECANCELED so | ||
659 | * that the packet is properly freed? | ||
660 | */ | ||
654 | if (s_req->busrequest) | 661 | if (s_req->busrequest) |
655 | ath6kl_sdio_free_bus_req(ar_sdio, s_req->busrequest); | 662 | ath6kl_sdio_free_bus_req(ar_sdio, s_req->busrequest); |
656 | kfree(s_req->virt_dma_buf); | 663 | kfree(s_req->virt_dma_buf); |
@@ -670,6 +677,11 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar) | |||
670 | int ret; | 677 | int ret; |
671 | bool virt_scat = false; | 678 | bool virt_scat = false; |
672 | 679 | ||
680 | if (ar_sdio->scatter_enabled) | ||
681 | return 0; | ||
682 | |||
683 | ar_sdio->scatter_enabled = true; | ||
684 | |||
673 | /* check if host supports scatter and it meets our requirements */ | 685 | /* check if host supports scatter and it meets our requirements */ |
674 | if (ar_sdio->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) { | 686 | if (ar_sdio->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) { |
675 | ath6kl_err("host only supports scatter of :%d entries, need: %d\n", | 687 | ath6kl_err("host only supports scatter of :%d entries, need: %d\n", |
@@ -762,6 +774,38 @@ static int ath6kl_sdio_resume(struct ath6kl *ar) | |||
762 | return 0; | 774 | return 0; |
763 | } | 775 | } |
764 | 776 | ||
777 | static void ath6kl_sdio_stop(struct ath6kl *ar) | ||
778 | { | ||
779 | struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); | ||
780 | struct bus_request *req, *tmp_req; | ||
781 | void *context; | ||
782 | |||
783 | /* FIXME: make sure that wq is not queued again */ | ||
784 | |||
785 | cancel_work_sync(&ar_sdio->wr_async_work); | ||
786 | |||
787 | spin_lock_bh(&ar_sdio->wr_async_lock); | ||
788 | |||
789 | list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq, list) { | ||
790 | list_del(&req->list); | ||
791 | |||
792 | if (req->scat_req) { | ||
793 | /* this is a scatter gather request */ | ||
794 | req->scat_req->status = -ECANCELED; | ||
795 | req->scat_req->complete(ar_sdio->ar->htc_target, | ||
796 | req->scat_req); | ||
797 | } else { | ||
798 | context = req->packet; | ||
799 | ath6kl_sdio_free_bus_req(ar_sdio, req); | ||
800 | ath6kl_hif_rw_comp_handler(context, -ECANCELED); | ||
801 | } | ||
802 | } | ||
803 | |||
804 | spin_unlock_bh(&ar_sdio->wr_async_lock); | ||
805 | |||
806 | WARN_ON(get_queue_depth(&ar_sdio->scat_req) != 4); | ||
807 | } | ||
808 | |||
765 | static const struct ath6kl_hif_ops ath6kl_sdio_ops = { | 809 | static const struct ath6kl_hif_ops ath6kl_sdio_ops = { |
766 | .read_write_sync = ath6kl_sdio_read_write_sync, | 810 | .read_write_sync = ath6kl_sdio_read_write_sync, |
767 | .write_async = ath6kl_sdio_write_async, | 811 | .write_async = ath6kl_sdio_write_async, |
@@ -776,6 +820,7 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = { | |||
776 | .resume = ath6kl_sdio_resume, | 820 | .resume = ath6kl_sdio_resume, |
777 | .power_on = ath6kl_sdio_power_on, | 821 | .power_on = ath6kl_sdio_power_on, |
778 | .power_off = ath6kl_sdio_power_off, | 822 | .power_off = ath6kl_sdio_power_off, |
823 | .stop = ath6kl_sdio_stop, | ||
779 | }; | 824 | }; |
780 | 825 | ||
781 | static int ath6kl_sdio_probe(struct sdio_func *func, | 826 | static int ath6kl_sdio_probe(struct sdio_func *func, |