aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-05-16 10:15:39 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2014-05-23 04:00:08 -0400
commit95bf21f97f09b724ed7d5eb9f0b3c5c664f0329e (patch)
tree536ee96c67d188445ff4f7a47806327a3f564c87 /drivers/net/wireless/ath
parent46acf7bb9b61289ea3353561142e3bf41119bd3e (diff)
ath10k: fix core start sequence
It was possible to call hif_stop() 2 times through ath10k_htc_connect_init() timeout failpath which could lead to double free_irq() kernel splat for multiple MSI interrupt case. Re-order init sequence to avoid this problem. The HTC stop shouldn't stop HIF implicitly since it doesn't implicitly start it. Since the re-ordering required some functions to be split/removed/renamed rename a few functions to make more sense while at it. Reported-By: Ben Greear <greearb@candelatech.com> Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c101
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.c6
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.c42
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h18
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c4
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h2
8 files changed, 76 insertions, 107 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 75b3dfbd6509..eca826ff393c 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -58,36 +58,6 @@ static void ath10k_send_suspend_complete(struct ath10k *ar)
58 complete(&ar->target_suspend); 58 complete(&ar->target_suspend);
59} 59}
60 60
61static int ath10k_init_connect_htc(struct ath10k *ar)
62{
63 int status;
64
65 status = ath10k_wmi_connect_htc_service(ar);
66 if (status)
67 goto conn_fail;
68
69 /* Start HTC */
70 status = ath10k_htc_start(&ar->htc);
71 if (status)
72 goto conn_fail;
73
74 /* Wait for WMI event to be ready */
75 status = ath10k_wmi_wait_for_service_ready(ar);
76 if (status <= 0) {
77 ath10k_warn("wmi service ready event not received");
78 status = -ETIMEDOUT;
79 goto timeout;
80 }
81
82 ath10k_dbg(ATH10K_DBG_BOOT, "boot wmi ready\n");
83 return 0;
84
85timeout:
86 ath10k_htc_stop(&ar->htc);
87conn_fail:
88 return status;
89}
90
91static int ath10k_init_configure_target(struct ath10k *ar) 61static int ath10k_init_configure_target(struct ath10k *ar)
92{ 62{
93 u32 param_host; 63 u32 param_host;
@@ -805,10 +775,28 @@ int ath10k_core_start(struct ath10k *ar)
805 goto err; 775 goto err;
806 } 776 }
807 777
778 status = ath10k_htt_init(ar);
779 if (status) {
780 ath10k_err("failed to init htt: %d\n", status);
781 goto err_wmi_detach;
782 }
783
784 status = ath10k_htt_tx_alloc(&ar->htt);
785 if (status) {
786 ath10k_err("failed to alloc htt tx: %d\n", status);
787 goto err_wmi_detach;
788 }
789
790 status = ath10k_htt_rx_alloc(&ar->htt);
791 if (status) {
792 ath10k_err("failed to alloc htt rx: %d\n", status);
793 goto err_htt_tx_detach;
794 }
795
808 status = ath10k_hif_start(ar); 796 status = ath10k_hif_start(ar);
809 if (status) { 797 if (status) {
810 ath10k_err("could not start HIF: %d\n", status); 798 ath10k_err("could not start HIF: %d\n", status);
811 goto err_wmi_detach; 799 goto err_htt_rx_detach;
812 } 800 }
813 801
814 status = ath10k_htc_wait_target(&ar->htc); 802 status = ath10k_htc_wait_target(&ar->htc);
@@ -817,15 +805,30 @@ int ath10k_core_start(struct ath10k *ar)
817 goto err_hif_stop; 805 goto err_hif_stop;
818 } 806 }
819 807
820 status = ath10k_htt_attach(ar); 808 status = ath10k_htt_connect(&ar->htt);
821 if (status) { 809 if (status) {
822 ath10k_err("could not attach htt (%d)\n", status); 810 ath10k_err("failed to connect htt (%d)\n", status);
823 goto err_hif_stop; 811 goto err_hif_stop;
824 } 812 }
825 813
826 status = ath10k_init_connect_htc(ar); 814 status = ath10k_wmi_connect(ar);
827 if (status) 815 if (status) {
828 goto err_htt_detach; 816 ath10k_err("could not connect wmi: %d\n", status);
817 goto err_hif_stop;
818 }
819
820 status = ath10k_htc_start(&ar->htc);
821 if (status) {
822 ath10k_err("failed to start htc: %d\n", status);
823 goto err_hif_stop;
824 }
825
826 status = ath10k_wmi_wait_for_service_ready(ar);
827 if (status <= 0) {
828 ath10k_warn("wmi service ready event not received");
829 status = -ETIMEDOUT;
830 goto err_htc_stop;
831 }
829 832
830 ath10k_dbg(ATH10K_DBG_BOOT, "firmware %s booted\n", 833 ath10k_dbg(ATH10K_DBG_BOOT, "firmware %s booted\n",
831 ar->hw->wiphy->fw_version); 834 ar->hw->wiphy->fw_version);
@@ -833,23 +836,25 @@ int ath10k_core_start(struct ath10k *ar)
833 status = ath10k_wmi_cmd_init(ar); 836 status = ath10k_wmi_cmd_init(ar);
834 if (status) { 837 if (status) {
835 ath10k_err("could not send WMI init command (%d)\n", status); 838 ath10k_err("could not send WMI init command (%d)\n", status);
836 goto err_disconnect_htc; 839 goto err_htc_stop;
837 } 840 }
838 841
839 status = ath10k_wmi_wait_for_unified_ready(ar); 842 status = ath10k_wmi_wait_for_unified_ready(ar);
840 if (status <= 0) { 843 if (status <= 0) {
841 ath10k_err("wmi unified ready event not received\n"); 844 ath10k_err("wmi unified ready event not received\n");
842 status = -ETIMEDOUT; 845 status = -ETIMEDOUT;
843 goto err_disconnect_htc; 846 goto err_htc_stop;
844 } 847 }
845 848
846 status = ath10k_htt_attach_target(&ar->htt); 849 status = ath10k_htt_setup(&ar->htt);
847 if (status) 850 if (status) {
848 goto err_disconnect_htc; 851 ath10k_err("failed to setup htt: %d\n", status);
852 goto err_htc_stop;
853 }
849 854
850 status = ath10k_debug_start(ar); 855 status = ath10k_debug_start(ar);
851 if (status) 856 if (status)
852 goto err_disconnect_htc; 857 goto err_htc_stop;
853 858
854 ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; 859 ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
855 INIT_LIST_HEAD(&ar->arvifs); 860 INIT_LIST_HEAD(&ar->arvifs);
@@ -868,12 +873,14 @@ int ath10k_core_start(struct ath10k *ar)
868 873
869 return 0; 874 return 0;
870 875
871err_disconnect_htc: 876err_htc_stop:
872 ath10k_htc_stop(&ar->htc); 877 ath10k_htc_stop(&ar->htc);
873err_htt_detach:
874 ath10k_htt_detach(&ar->htt);
875err_hif_stop: 878err_hif_stop:
876 ath10k_hif_stop(ar); 879 ath10k_hif_stop(ar);
880err_htt_rx_detach:
881 ath10k_htt_rx_free(&ar->htt);
882err_htt_tx_detach:
883 ath10k_htt_tx_free(&ar->htt);
877err_wmi_detach: 884err_wmi_detach:
878 ath10k_wmi_detach(ar); 885 ath10k_wmi_detach(ar);
879err: 886err:
@@ -913,7 +920,9 @@ void ath10k_core_stop(struct ath10k *ar)
913 920
914 ath10k_debug_stop(ar); 921 ath10k_debug_stop(ar);
915 ath10k_htc_stop(&ar->htc); 922 ath10k_htc_stop(&ar->htc);
916 ath10k_htt_detach(&ar->htt); 923 ath10k_hif_stop(ar);
924 ath10k_htt_tx_free(&ar->htt);
925 ath10k_htt_rx_free(&ar->htt);
917 ath10k_wmi_detach(ar); 926 ath10k_wmi_detach(ar);
918} 927}
919EXPORT_SYMBOL(ath10k_core_stop); 928EXPORT_SYMBOL(ath10k_core_stop);
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 5b58dbb17416..e493db4b4a41 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -830,17 +830,11 @@ int ath10k_htc_start(struct ath10k_htc *htc)
830 return 0; 830 return 0;
831} 831}
832 832
833/*
834 * stop HTC communications, i.e. stop interrupt reception, and flush all
835 * queued buffers
836 */
837void ath10k_htc_stop(struct ath10k_htc *htc) 833void ath10k_htc_stop(struct ath10k_htc *htc)
838{ 834{
839 spin_lock_bh(&htc->tx_lock); 835 spin_lock_bh(&htc->tx_lock);
840 htc->stopped = true; 836 htc->stopped = true;
841 spin_unlock_bh(&htc->tx_lock); 837 spin_unlock_bh(&htc->tx_lock);
842
843 ath10k_hif_stop(htc->ar);
844} 838}
845 839
846/* registered target arrival callback from the HIF layer */ 840/* registered target arrival callback from the HIF layer */
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c
index 69697af59ce0..19c12cc8d663 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -22,7 +22,7 @@
22#include "core.h" 22#include "core.h"
23#include "debug.h" 23#include "debug.h"
24 24
25static int ath10k_htt_htc_attach(struct ath10k_htt *htt) 25int ath10k_htt_connect(struct ath10k_htt *htt)
26{ 26{
27 struct ath10k_htc_svc_conn_req conn_req; 27 struct ath10k_htc_svc_conn_req conn_req;
28 struct ath10k_htc_svc_conn_resp conn_resp; 28 struct ath10k_htc_svc_conn_resp conn_resp;
@@ -48,39 +48,14 @@ static int ath10k_htt_htc_attach(struct ath10k_htt *htt)
48 return 0; 48 return 0;
49} 49}
50 50
51int ath10k_htt_attach(struct ath10k *ar) 51int ath10k_htt_init(struct ath10k *ar)
52{ 52{
53 struct ath10k_htt *htt = &ar->htt; 53 struct ath10k_htt *htt = &ar->htt;
54 int ret;
55 54
56 htt->ar = ar; 55 htt->ar = ar;
57 htt->max_throughput_mbps = 800; 56 htt->max_throughput_mbps = 800;
58 57
59 /* 58 /*
60 * Connect to HTC service.
61 * This has to be done before calling ath10k_htt_rx_attach,
62 * since ath10k_htt_rx_attach involves sending a rx ring configure
63 * message to the target.
64 */
65 ret = ath10k_htt_htc_attach(htt);
66 if (ret) {
67 ath10k_err("could not attach htt htc (%d)\n", ret);
68 goto err_htc_attach;
69 }
70
71 ret = ath10k_htt_tx_attach(htt);
72 if (ret) {
73 ath10k_err("could not attach htt tx (%d)\n", ret);
74 goto err_htc_attach;
75 }
76
77 ret = ath10k_htt_rx_attach(htt);
78 if (ret) {
79 ath10k_err("could not attach htt rx (%d)\n", ret);
80 goto err_rx_attach;
81 }
82
83 /*
84 * Prefetch enough data to satisfy target 59 * Prefetch enough data to satisfy target
85 * classification engine. 60 * classification engine.
86 * This is for LL chips. HL chips will probably 61 * This is for LL chips. HL chips will probably
@@ -93,11 +68,6 @@ int ath10k_htt_attach(struct ath10k *ar)
93 2; /* ip4 dscp or ip6 priority */ 68 2; /* ip4 dscp or ip6 priority */
94 69
95 return 0; 70 return 0;
96
97err_rx_attach:
98 ath10k_htt_tx_detach(htt);
99err_htc_attach:
100 return ret;
101} 71}
102 72
103#define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ) 73#define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ)
@@ -117,7 +87,7 @@ static int ath10k_htt_verify_version(struct ath10k_htt *htt)
117 return 0; 87 return 0;
118} 88}
119 89
120int ath10k_htt_attach_target(struct ath10k_htt *htt) 90int ath10k_htt_setup(struct ath10k_htt *htt)
121{ 91{
122 int status; 92 int status;
123 93
@@ -140,9 +110,3 @@ int ath10k_htt_attach_target(struct ath10k_htt *htt)
140 110
141 return ath10k_htt_send_rx_ring_cfg_ll(htt); 111 return ath10k_htt_send_rx_ring_cfg_ll(htt);
142} 112}
143
144void ath10k_htt_detach(struct ath10k_htt *htt)
145{
146 ath10k_htt_rx_detach(htt);
147 ath10k_htt_tx_detach(htt);
148}
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 645a563e3fb9..9a263462c793 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1328,14 +1328,16 @@ struct htt_rx_desc {
1328#define HTT_LOG2_MAX_CACHE_LINE_SIZE 7 /* 2^7 = 128 */ 1328#define HTT_LOG2_MAX_CACHE_LINE_SIZE 7 /* 2^7 = 128 */
1329#define HTT_MAX_CACHE_LINE_SIZE_MASK ((1 << HTT_LOG2_MAX_CACHE_LINE_SIZE) - 1) 1329#define HTT_MAX_CACHE_LINE_SIZE_MASK ((1 << HTT_LOG2_MAX_CACHE_LINE_SIZE) - 1)
1330 1330
1331int ath10k_htt_attach(struct ath10k *ar); 1331int ath10k_htt_connect(struct ath10k_htt *htt);
1332int ath10k_htt_attach_target(struct ath10k_htt *htt); 1332int ath10k_htt_init(struct ath10k *ar);
1333void ath10k_htt_detach(struct ath10k_htt *htt); 1333int ath10k_htt_setup(struct ath10k_htt *htt);
1334 1334
1335int ath10k_htt_tx_attach(struct ath10k_htt *htt); 1335int ath10k_htt_tx_alloc(struct ath10k_htt *htt);
1336void ath10k_htt_tx_detach(struct ath10k_htt *htt); 1336void ath10k_htt_tx_free(struct ath10k_htt *htt);
1337int ath10k_htt_rx_attach(struct ath10k_htt *htt); 1337
1338void ath10k_htt_rx_detach(struct ath10k_htt *htt); 1338int ath10k_htt_rx_alloc(struct ath10k_htt *htt);
1339void ath10k_htt_rx_free(struct ath10k_htt *htt);
1340
1339void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb); 1341void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb);
1340void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb); 1342void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
1341int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt); 1343int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index ac6a5fe75c87..f744e355c70a 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -243,7 +243,7 @@ static void ath10k_htt_rx_ring_clean_up(struct ath10k_htt *htt)
243 } 243 }
244} 244}
245 245
246void ath10k_htt_rx_detach(struct ath10k_htt *htt) 246void ath10k_htt_rx_free(struct ath10k_htt *htt)
247{ 247{
248 del_timer_sync(&htt->rx_ring.refill_retry_timer); 248 del_timer_sync(&htt->rx_ring.refill_retry_timer);
249 tasklet_kill(&htt->rx_replenish_task); 249 tasklet_kill(&htt->rx_replenish_task);
@@ -492,7 +492,7 @@ static void ath10k_htt_rx_replenish_task(unsigned long ptr)
492 ath10k_htt_rx_msdu_buff_replenish(htt); 492 ath10k_htt_rx_msdu_buff_replenish(htt);
493} 493}
494 494
495int ath10k_htt_rx_attach(struct ath10k_htt *htt) 495int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
496{ 496{
497 dma_addr_t paddr; 497 dma_addr_t paddr;
498 void *vaddr; 498 void *vaddr;
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 7a3e2e40dd5c..7064354d1f4f 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -83,7 +83,7 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id)
83 __clear_bit(msdu_id, htt->used_msdu_ids); 83 __clear_bit(msdu_id, htt->used_msdu_ids);
84} 84}
85 85
86int ath10k_htt_tx_attach(struct ath10k_htt *htt) 86int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
87{ 87{
88 spin_lock_init(&htt->tx_lock); 88 spin_lock_init(&htt->tx_lock);
89 init_waitqueue_head(&htt->empty_tx_wq); 89 init_waitqueue_head(&htt->empty_tx_wq);
@@ -120,7 +120,7 @@ int ath10k_htt_tx_attach(struct ath10k_htt *htt)
120 return 0; 120 return 0;
121} 121}
122 122
123static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt) 123static void ath10k_htt_tx_free_pending(struct ath10k_htt *htt)
124{ 124{
125 struct htt_tx_done tx_done = {0}; 125 struct htt_tx_done tx_done = {0};
126 int msdu_id; 126 int msdu_id;
@@ -141,9 +141,9 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt)
141 spin_unlock_bh(&htt->tx_lock); 141 spin_unlock_bh(&htt->tx_lock);
142} 142}
143 143
144void ath10k_htt_tx_detach(struct ath10k_htt *htt) 144void ath10k_htt_tx_free(struct ath10k_htt *htt)
145{ 145{
146 ath10k_htt_tx_cleanup_pending(htt); 146 ath10k_htt_tx_free_pending(htt);
147 kfree(htt->pending_tx); 147 kfree(htt->pending_tx);
148 kfree(htt->used_msdu_ids); 148 kfree(htt->used_msdu_ids);
149 dma_pool_destroy(htt->tx_pool); 149 dma_pool_destroy(htt->tx_pool);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index e355d5e4928d..4b7782a529ac 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2375,7 +2375,7 @@ void ath10k_wmi_detach(struct ath10k *ar)
2375 ar->wmi.num_mem_chunks = 0; 2375 ar->wmi.num_mem_chunks = 0;
2376} 2376}
2377 2377
2378int ath10k_wmi_connect_htc_service(struct ath10k *ar) 2378int ath10k_wmi_connect(struct ath10k *ar)
2379{ 2379{
2380 int status; 2380 int status;
2381 struct ath10k_htc_svc_conn_req conn_req; 2381 struct ath10k_htc_svc_conn_req conn_req;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index e59b245b79b9..89ef3b3749eb 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -4259,7 +4259,7 @@ void ath10k_wmi_detach(struct ath10k *ar);
4259int ath10k_wmi_wait_for_service_ready(struct ath10k *ar); 4259int ath10k_wmi_wait_for_service_ready(struct ath10k *ar);
4260int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar); 4260int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
4261 4261
4262int ath10k_wmi_connect_htc_service(struct ath10k *ar); 4262int ath10k_wmi_connect(struct ath10k *ar);
4263int ath10k_wmi_pdev_set_channel(struct ath10k *ar, 4263int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
4264 const struct wmi_channel_arg *); 4264 const struct wmi_channel_arg *);
4265int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt); 4265int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);