aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorKalle Valo <kvalo@qca.qualcomm.com>2011-10-30 15:15:57 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2011-11-11 05:58:58 -0500
commit32a07e4448f78158a75f7c1f0056289647d83946 (patch)
treec248329a3c55b151c09bce26c0aa2556e31c8f30 /drivers/net/wireless
parentcd4b8b85800a47dc68b9282ffc3a88b82e77f242 (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')
-rw-r--r--drivers/net/wireless/ath/ath6kl/hif-ops.h7
-rw-r--r--drivers/net/wireless/ath/ath6kl/hif.h1
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c45
3 files changed, 53 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/hif-ops.h b/drivers/net/wireless/ath/ath6kl/hif-ops.h
index 34adc77ffb30..50fd3e992811 100644
--- a/drivers/net/wireless/ath/ath6kl/hif-ops.h
+++ b/drivers/net/wireless/ath/ath6kl/hif-ops.h
@@ -111,4 +111,11 @@ static inline int ath6kl_hif_power_off(struct ath6kl *ar)
111 return ar->hif_ops->power_off(ar); 111 return ar->hif_ops->power_off(ar);
112} 112}
113 113
114static inline void ath6kl_hif_stop(struct ath6kl *ar)
115{
116 ath6kl_dbg(ATH6KL_DBG_HIF, "hif stop\n");
117
118 ar->hif_ops->stop(ar);
119}
120
114#endif 121#endif
diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h
index 78a6c79f8cab..814386d19b83 100644
--- a/drivers/net/wireless/ath/ath6kl/hif.h
+++ b/drivers/net/wireless/ath/ath6kl/hif.h
@@ -246,6 +246,7 @@ struct ath6kl_hif_ops {
246 int (*resume)(struct ath6kl *ar); 246 int (*resume)(struct ath6kl *ar);
247 int (*power_on)(struct ath6kl *ar); 247 int (*power_on)(struct ath6kl *ar);
248 int (*power_off)(struct ath6kl *ar); 248 int (*power_off)(struct ath6kl *ar);
249 void (*stop)(struct ath6kl *ar);
249}; 250};
250 251
251int ath6kl_hif_setup(struct ath6kl_device *dev); 252int ath6kl_hif_setup(struct ath6kl_device *dev);
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
777static 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
765static const struct ath6kl_hif_ops ath6kl_sdio_ops = { 809static 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
781static int ath6kl_sdio_probe(struct sdio_func *func, 826static int ath6kl_sdio_probe(struct sdio_func *func,