hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/net/wireless/ath/ath10k/htc.c
....@@ -1,18 +1,7 @@
1
+// SPDX-License-Identifier: ISC
12 /*
23 * Copyright (c) 2005-2011 Atheros Communications Inc.
34 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
4
- *
5
- * Permission to use, copy, modify, and/or distribute this software for any
6
- * purpose with or without fee is hereby granted, provided that the above
7
- * copyright notice and this permission notice appear in all copies.
8
- *
9
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
165 */
176
187 #include "core.h"
....@@ -53,7 +42,8 @@
5342 {
5443 struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
5544
56
- dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
45
+ if (htc->ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
46
+ dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
5747 skb_pull(skb, sizeof(struct ath10k_htc_hdr));
5848 }
5949
....@@ -61,14 +51,21 @@
6151 struct sk_buff *skb)
6252 {
6353 struct ath10k *ar = ep->htc->ar;
54
+ struct ath10k_htc_hdr *hdr;
6455
6556 ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__,
6657 ep->eid, skb);
6758
59
+ hdr = (struct ath10k_htc_hdr *)skb->data;
6860 ath10k_htc_restore_tx_skb(ep->htc, skb);
6961
7062 if (!ep->ep_ops.ep_tx_complete) {
7163 ath10k_warn(ar, "no tx handler for eid %d\n", ep->eid);
64
+ dev_kfree_skb_any(skb);
65
+ return;
66
+ }
67
+
68
+ if (hdr->flags & ATH10K_HTC_FLAG_SEND_BUNDLE) {
7269 dev_kfree_skb_any(skb);
7370 return;
7471 }
....@@ -83,15 +80,74 @@
8380 struct ath10k_htc_hdr *hdr;
8481
8582 hdr = (struct ath10k_htc_hdr *)skb->data;
83
+ memset(hdr, 0, sizeof(struct ath10k_htc_hdr));
8684
8785 hdr->eid = ep->eid;
8886 hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr));
8987 hdr->flags = 0;
90
- hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE;
88
+ if (ep->tx_credit_flow_enabled && !ep->bundle_tx)
89
+ hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE;
9190
9291 spin_lock_bh(&ep->htc->tx_lock);
9392 hdr->seq_no = ep->seq_no++;
9493 spin_unlock_bh(&ep->htc->tx_lock);
94
+}
95
+
96
+static int ath10k_htc_consume_credit(struct ath10k_htc_ep *ep,
97
+ unsigned int len,
98
+ bool consume)
99
+{
100
+ struct ath10k_htc *htc = ep->htc;
101
+ struct ath10k *ar = htc->ar;
102
+ enum ath10k_htc_ep_id eid = ep->eid;
103
+ int credits, ret = 0;
104
+
105
+ if (!ep->tx_credit_flow_enabled)
106
+ return 0;
107
+
108
+ credits = DIV_ROUND_UP(len, ep->tx_credit_size);
109
+ spin_lock_bh(&htc->tx_lock);
110
+
111
+ if (ep->tx_credits < credits) {
112
+ ath10k_dbg(ar, ATH10K_DBG_HTC,
113
+ "htc insufficient credits ep %d required %d available %d consume %d\n",
114
+ eid, credits, ep->tx_credits, consume);
115
+ ret = -EAGAIN;
116
+ goto unlock;
117
+ }
118
+
119
+ if (consume) {
120
+ ep->tx_credits -= credits;
121
+ ath10k_dbg(ar, ATH10K_DBG_HTC,
122
+ "htc ep %d consumed %d credits total %d\n",
123
+ eid, credits, ep->tx_credits);
124
+ }
125
+
126
+unlock:
127
+ spin_unlock_bh(&htc->tx_lock);
128
+ return ret;
129
+}
130
+
131
+static void ath10k_htc_release_credit(struct ath10k_htc_ep *ep, unsigned int len)
132
+{
133
+ struct ath10k_htc *htc = ep->htc;
134
+ struct ath10k *ar = htc->ar;
135
+ enum ath10k_htc_ep_id eid = ep->eid;
136
+ int credits;
137
+
138
+ if (!ep->tx_credit_flow_enabled)
139
+ return;
140
+
141
+ credits = DIV_ROUND_UP(len, ep->tx_credit_size);
142
+ spin_lock_bh(&htc->tx_lock);
143
+ ep->tx_credits += credits;
144
+ ath10k_dbg(ar, ATH10K_DBG_HTC,
145
+ "htc ep %d reverted %d credits back total %d\n",
146
+ eid, credits, ep->tx_credits);
147
+ spin_unlock_bh(&htc->tx_lock);
148
+
149
+ if (ep->ep_ops.ep_tx_credits)
150
+ ep->ep_ops.ep_tx_credits(htc->ar);
95151 }
96152
97153 int ath10k_htc_send(struct ath10k_htc *htc,
....@@ -103,8 +159,8 @@
103159 struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
104160 struct ath10k_hif_sg_item sg_item;
105161 struct device *dev = htc->ar->dev;
106
- int credits = 0;
107162 int ret;
163
+ unsigned int skb_len;
108164
109165 if (htc->ar->state == ATH10K_STATE_WEDGED)
110166 return -ECOMM;
....@@ -116,32 +172,22 @@
116172
117173 skb_push(skb, sizeof(struct ath10k_htc_hdr));
118174
119
- if (ep->tx_credit_flow_enabled) {
120
- credits = DIV_ROUND_UP(skb->len, htc->target_credit_size);
121
- spin_lock_bh(&htc->tx_lock);
122
- if (ep->tx_credits < credits) {
123
- ath10k_dbg(ar, ATH10K_DBG_HTC,
124
- "htc insufficient credits ep %d required %d available %d\n",
125
- eid, credits, ep->tx_credits);
126
- spin_unlock_bh(&htc->tx_lock);
127
- ret = -EAGAIN;
128
- goto err_pull;
129
- }
130
- ep->tx_credits -= credits;
131
- ath10k_dbg(ar, ATH10K_DBG_HTC,
132
- "htc ep %d consumed %d credits (total %d)\n",
133
- eid, credits, ep->tx_credits);
134
- spin_unlock_bh(&htc->tx_lock);
135
- }
175
+ skb_len = skb->len;
176
+ ret = ath10k_htc_consume_credit(ep, skb_len, true);
177
+ if (ret)
178
+ goto err_pull;
136179
137180 ath10k_htc_prepare_tx_skb(ep, skb);
138181
139182 skb_cb->eid = eid;
140
- skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
141
- ret = dma_mapping_error(dev, skb_cb->paddr);
142
- if (ret) {
143
- ret = -EIO;
144
- goto err_credits;
183
+ if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) {
184
+ skb_cb->paddr = dma_map_single(dev, skb->data, skb->len,
185
+ DMA_TO_DEVICE);
186
+ ret = dma_mapping_error(dev, skb_cb->paddr);
187
+ if (ret) {
188
+ ret = -EIO;
189
+ goto err_credits;
190
+ }
145191 }
146192
147193 sg_item.transfer_id = ep->eid;
....@@ -157,19 +203,10 @@
157203 return 0;
158204
159205 err_unmap:
160
- dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
206
+ if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
207
+ dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
161208 err_credits:
162
- if (ep->tx_credit_flow_enabled) {
163
- spin_lock_bh(&htc->tx_lock);
164
- ep->tx_credits += credits;
165
- ath10k_dbg(ar, ATH10K_DBG_HTC,
166
- "htc ep %d reverted %d credits back (total %d)\n",
167
- eid, credits, ep->tx_credits);
168
- spin_unlock_bh(&htc->tx_lock);
169
-
170
- if (ep->ep_ops.ep_tx_credits)
171
- ep->ep_ops.ep_tx_credits(htc->ar);
172
- }
209
+ ath10k_htc_release_credit(ep, skb_len);
173210 err_pull:
174211 skb_pull(skb, sizeof(struct ath10k_htc_hdr));
175212 return ret;
....@@ -274,7 +311,7 @@
274311 struct ath10k *ar = htc->ar;
275312 int bundle_cnt = len / sizeof(*report);
276313
277
- if (!bundle_cnt || (bundle_cnt > HTC_HOST_MAX_MSG_PER_RX_BUNDLE)) {
314
+ if (!bundle_cnt || (bundle_cnt > htc->max_msgs_per_htc_bundle)) {
278315 ath10k_warn(ar, "Invalid lookahead bundle count: %d\n",
279316 bundle_cnt);
280317 return -EINVAL;
....@@ -585,6 +622,278 @@
585622 return allocation;
586623 }
587624
625
+static int ath10k_htc_send_bundle(struct ath10k_htc_ep *ep,
626
+ struct sk_buff *bundle_skb,
627
+ struct sk_buff_head *tx_save_head)
628
+{
629
+ struct ath10k_hif_sg_item sg_item;
630
+ struct ath10k_htc *htc = ep->htc;
631
+ struct ath10k *ar = htc->ar;
632
+ struct sk_buff *skb;
633
+ int ret, cn = 0;
634
+ unsigned int skb_len;
635
+
636
+ ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle skb len %d\n", bundle_skb->len);
637
+ skb_len = bundle_skb->len;
638
+ ret = ath10k_htc_consume_credit(ep, skb_len, true);
639
+
640
+ if (!ret) {
641
+ sg_item.transfer_id = ep->eid;
642
+ sg_item.transfer_context = bundle_skb;
643
+ sg_item.vaddr = bundle_skb->data;
644
+ sg_item.len = bundle_skb->len;
645
+
646
+ ret = ath10k_hif_tx_sg(htc->ar, ep->ul_pipe_id, &sg_item, 1);
647
+ if (ret)
648
+ ath10k_htc_release_credit(ep, skb_len);
649
+ }
650
+
651
+ if (ret)
652
+ dev_kfree_skb_any(bundle_skb);
653
+
654
+ for (cn = 0; (skb = skb_dequeue_tail(tx_save_head)); cn++) {
655
+ if (ret) {
656
+ skb_pull(skb, sizeof(struct ath10k_htc_hdr));
657
+ skb_queue_head(&ep->tx_req_head, skb);
658
+ } else {
659
+ skb_queue_tail(&ep->tx_complete_head, skb);
660
+ }
661
+ }
662
+
663
+ if (!ret)
664
+ queue_work(ar->workqueue_tx_complete, &ar->tx_complete_work);
665
+
666
+ ath10k_dbg(ar, ATH10K_DBG_HTC,
667
+ "bundle tx status %d eid %d req count %d count %d len %d\n",
668
+ ret, ep->eid, skb_queue_len(&ep->tx_req_head), cn, skb_len);
669
+ return ret;
670
+}
671
+
672
+static void ath10k_htc_send_one_skb(struct ath10k_htc_ep *ep, struct sk_buff *skb)
673
+{
674
+ struct ath10k_htc *htc = ep->htc;
675
+ struct ath10k *ar = htc->ar;
676
+ int ret;
677
+
678
+ ret = ath10k_htc_send(htc, ep->eid, skb);
679
+
680
+ if (ret)
681
+ skb_queue_head(&ep->tx_req_head, skb);
682
+
683
+ ath10k_dbg(ar, ATH10K_DBG_HTC, "tx one status %d eid %d len %d pending count %d\n",
684
+ ret, ep->eid, skb->len, skb_queue_len(&ep->tx_req_head));
685
+}
686
+
687
+static int ath10k_htc_send_bundle_skbs(struct ath10k_htc_ep *ep)
688
+{
689
+ struct ath10k_htc *htc = ep->htc;
690
+ struct sk_buff *bundle_skb, *skb;
691
+ struct sk_buff_head tx_save_head;
692
+ struct ath10k_htc_hdr *hdr;
693
+ u8 *bundle_buf;
694
+ int ret = 0, credit_pad, credit_remainder, trans_len, bundles_left = 0;
695
+
696
+ if (htc->ar->state == ATH10K_STATE_WEDGED)
697
+ return -ECOMM;
698
+
699
+ if (ep->tx_credit_flow_enabled &&
700
+ ep->tx_credits < ATH10K_MIN_CREDIT_PER_HTC_TX_BUNDLE)
701
+ return 0;
702
+
703
+ bundles_left = ATH10K_MAX_MSG_PER_HTC_TX_BUNDLE * ep->tx_credit_size;
704
+ bundle_skb = dev_alloc_skb(bundles_left);
705
+
706
+ if (!bundle_skb)
707
+ return -ENOMEM;
708
+
709
+ bundle_buf = bundle_skb->data;
710
+ skb_queue_head_init(&tx_save_head);
711
+
712
+ while (true) {
713
+ skb = skb_dequeue(&ep->tx_req_head);
714
+ if (!skb)
715
+ break;
716
+
717
+ credit_pad = 0;
718
+ trans_len = skb->len + sizeof(*hdr);
719
+ credit_remainder = trans_len % ep->tx_credit_size;
720
+
721
+ if (credit_remainder != 0) {
722
+ credit_pad = ep->tx_credit_size - credit_remainder;
723
+ trans_len += credit_pad;
724
+ }
725
+
726
+ ret = ath10k_htc_consume_credit(ep,
727
+ bundle_buf + trans_len - bundle_skb->data,
728
+ false);
729
+ if (ret) {
730
+ skb_queue_head(&ep->tx_req_head, skb);
731
+ break;
732
+ }
733
+
734
+ if (bundles_left < trans_len) {
735
+ bundle_skb->len = bundle_buf - bundle_skb->data;
736
+ ret = ath10k_htc_send_bundle(ep, bundle_skb, &tx_save_head);
737
+
738
+ if (ret) {
739
+ skb_queue_head(&ep->tx_req_head, skb);
740
+ return ret;
741
+ }
742
+
743
+ if (skb_queue_len(&ep->tx_req_head) == 0) {
744
+ ath10k_htc_send_one_skb(ep, skb);
745
+ return ret;
746
+ }
747
+
748
+ if (ep->tx_credit_flow_enabled &&
749
+ ep->tx_credits < ATH10K_MIN_CREDIT_PER_HTC_TX_BUNDLE) {
750
+ skb_queue_head(&ep->tx_req_head, skb);
751
+ return 0;
752
+ }
753
+
754
+ bundles_left =
755
+ ATH10K_MAX_MSG_PER_HTC_TX_BUNDLE * ep->tx_credit_size;
756
+ bundle_skb = dev_alloc_skb(bundles_left);
757
+
758
+ if (!bundle_skb) {
759
+ skb_queue_head(&ep->tx_req_head, skb);
760
+ return -ENOMEM;
761
+ }
762
+ bundle_buf = bundle_skb->data;
763
+ skb_queue_head_init(&tx_save_head);
764
+ }
765
+
766
+ skb_push(skb, sizeof(struct ath10k_htc_hdr));
767
+ ath10k_htc_prepare_tx_skb(ep, skb);
768
+
769
+ memcpy(bundle_buf, skb->data, skb->len);
770
+ hdr = (struct ath10k_htc_hdr *)bundle_buf;
771
+ hdr->flags |= ATH10K_HTC_FLAG_SEND_BUNDLE;
772
+ hdr->pad_len = __cpu_to_le16(credit_pad);
773
+ bundle_buf += trans_len;
774
+ bundles_left -= trans_len;
775
+ skb_queue_tail(&tx_save_head, skb);
776
+ }
777
+
778
+ if (bundle_buf != bundle_skb->data) {
779
+ bundle_skb->len = bundle_buf - bundle_skb->data;
780
+ ret = ath10k_htc_send_bundle(ep, bundle_skb, &tx_save_head);
781
+ } else {
782
+ dev_kfree_skb_any(bundle_skb);
783
+ }
784
+
785
+ return ret;
786
+}
787
+
788
+static void ath10k_htc_bundle_tx_work(struct work_struct *work)
789
+{
790
+ struct ath10k *ar = container_of(work, struct ath10k, bundle_tx_work);
791
+ struct ath10k_htc_ep *ep;
792
+ struct sk_buff *skb;
793
+ int i;
794
+
795
+ for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) {
796
+ ep = &ar->htc.endpoint[i];
797
+
798
+ if (!ep->bundle_tx)
799
+ continue;
800
+
801
+ ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle tx work eid %d count %d\n",
802
+ ep->eid, skb_queue_len(&ep->tx_req_head));
803
+
804
+ if (skb_queue_len(&ep->tx_req_head) >=
805
+ ATH10K_MIN_MSG_PER_HTC_TX_BUNDLE) {
806
+ ath10k_htc_send_bundle_skbs(ep);
807
+ } else {
808
+ skb = skb_dequeue(&ep->tx_req_head);
809
+
810
+ if (!skb)
811
+ continue;
812
+ ath10k_htc_send_one_skb(ep, skb);
813
+ }
814
+ }
815
+}
816
+
817
+static void ath10k_htc_tx_complete_work(struct work_struct *work)
818
+{
819
+ struct ath10k *ar = container_of(work, struct ath10k, tx_complete_work);
820
+ struct ath10k_htc_ep *ep;
821
+ enum ath10k_htc_ep_id eid;
822
+ struct sk_buff *skb;
823
+ int i;
824
+
825
+ for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) {
826
+ ep = &ar->htc.endpoint[i];
827
+ eid = ep->eid;
828
+ if (ep->bundle_tx && eid == ar->htt.eid) {
829
+ ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle tx complete eid %d pending complete count%d\n",
830
+ ep->eid, skb_queue_len(&ep->tx_complete_head));
831
+
832
+ while (true) {
833
+ skb = skb_dequeue(&ep->tx_complete_head);
834
+ if (!skb)
835
+ break;
836
+ ath10k_htc_notify_tx_completion(ep, skb);
837
+ }
838
+ }
839
+ }
840
+}
841
+
842
+int ath10k_htc_send_hl(struct ath10k_htc *htc,
843
+ enum ath10k_htc_ep_id eid,
844
+ struct sk_buff *skb)
845
+{
846
+ struct ath10k_htc_ep *ep = &htc->endpoint[eid];
847
+ struct ath10k *ar = htc->ar;
848
+
849
+ if (sizeof(struct ath10k_htc_hdr) + skb->len > ep->tx_credit_size) {
850
+ ath10k_dbg(ar, ATH10K_DBG_HTC, "tx exceed max len %d\n", skb->len);
851
+ return -ENOMEM;
852
+ }
853
+
854
+ ath10k_dbg(ar, ATH10K_DBG_HTC, "htc send hl eid %d bundle %d tx count %d len %d\n",
855
+ eid, ep->bundle_tx, skb_queue_len(&ep->tx_req_head), skb->len);
856
+
857
+ if (ep->bundle_tx) {
858
+ skb_queue_tail(&ep->tx_req_head, skb);
859
+ queue_work(ar->workqueue, &ar->bundle_tx_work);
860
+ return 0;
861
+ } else {
862
+ return ath10k_htc_send(htc, eid, skb);
863
+ }
864
+}
865
+
866
+void ath10k_htc_setup_tx_req(struct ath10k_htc_ep *ep)
867
+{
868
+ if (ep->htc->max_msgs_per_htc_bundle >= ATH10K_MIN_MSG_PER_HTC_TX_BUNDLE &&
869
+ !ep->bundle_tx) {
870
+ ep->bundle_tx = true;
871
+ skb_queue_head_init(&ep->tx_req_head);
872
+ skb_queue_head_init(&ep->tx_complete_head);
873
+ }
874
+}
875
+
876
+void ath10k_htc_stop_hl(struct ath10k *ar)
877
+{
878
+ struct ath10k_htc_ep *ep;
879
+ int i;
880
+
881
+ cancel_work_sync(&ar->bundle_tx_work);
882
+ cancel_work_sync(&ar->tx_complete_work);
883
+
884
+ for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) {
885
+ ep = &ar->htc.endpoint[i];
886
+
887
+ if (!ep->bundle_tx)
888
+ continue;
889
+
890
+ ath10k_dbg(ar, ATH10K_DBG_HTC, "stop tx work eid %d count %d\n",
891
+ ep->eid, skb_queue_len(&ep->tx_req_head));
892
+
893
+ skb_queue_purge(&ep->tx_req_head);
894
+ }
895
+}
896
+
588897 int ath10k_htc_wait_target(struct ath10k_htc *htc)
589898 {
590899 struct ath10k *ar = htc->ar;
....@@ -653,15 +962,32 @@
653962 */
654963 if (htc->control_resp_len >=
655964 sizeof(msg->hdr) + sizeof(msg->ready_ext)) {
965
+ htc->alt_data_credit_size =
966
+ __le16_to_cpu(msg->ready_ext.reserved) &
967
+ ATH10K_HTC_MSG_READY_EXT_ALT_DATA_MASK;
656968 htc->max_msgs_per_htc_bundle =
657969 min_t(u8, msg->ready_ext.max_msgs_per_htc_bundle,
658970 HTC_HOST_MAX_MSG_PER_RX_BUNDLE);
659971 ath10k_dbg(ar, ATH10K_DBG_HTC,
660
- "Extended ready message. RX bundle size: %d\n",
661
- htc->max_msgs_per_htc_bundle);
972
+ "Extended ready message RX bundle size %d alt size %d\n",
973
+ htc->max_msgs_per_htc_bundle,
974
+ htc->alt_data_credit_size);
662975 }
663976
977
+ INIT_WORK(&ar->bundle_tx_work, ath10k_htc_bundle_tx_work);
978
+ INIT_WORK(&ar->tx_complete_work, ath10k_htc_tx_complete_work);
979
+
664980 return 0;
981
+}
982
+
983
+void ath10k_htc_change_tx_credit_flow(struct ath10k_htc *htc,
984
+ enum ath10k_htc_ep_id eid,
985
+ bool enable)
986
+{
987
+ struct ath10k *ar = htc->ar;
988
+ struct ath10k_htc_ep *ep = &ar->htc.endpoint[eid];
989
+
990
+ ep->tx_credit_flow_enabled = enable;
665991 }
666992
667993 int ath10k_htc_connect_service(struct ath10k_htc *htc,
....@@ -795,6 +1121,11 @@
7951121 ep->max_tx_queue_depth = conn_req->max_send_queue_depth;
7961122 ep->max_ep_message_len = __le16_to_cpu(resp_msg->max_msg_size);
7971123 ep->tx_credits = tx_alloc;
1124
+ ep->tx_credit_size = htc->target_credit_size;
1125
+
1126
+ if (conn_req->service_id == ATH10K_HTC_SVC_ID_HTT_DATA_MSG &&
1127
+ htc->alt_data_credit_size != 0)
1128
+ ep->tx_credit_size = htc->alt_data_credit_size;
7981129
7991130 /* copy all the callbacks */
8001131 ep->ep_ops = conn_req->ep_ops;
....@@ -803,8 +1134,11 @@
8031134 ep->service_id,
8041135 &ep->ul_pipe_id,
8051136 &ep->dl_pipe_id);
806
- if (status)
1137
+ if (status) {
1138
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "unsupported HTC service id: %d\n",
1139
+ ep->service_id);
8071140 return status;
1141
+ }
8081142
8091143 ath10k_dbg(ar, ATH10K_DBG_BOOT,
8101144 "boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n",
....@@ -838,6 +1172,56 @@
8381172 return skb;
8391173 }
8401174
1175
+static void ath10k_htc_pktlog_process_rx(struct ath10k *ar, struct sk_buff *skb)
1176
+{
1177
+ trace_ath10k_htt_pktlog(ar, skb->data, skb->len);
1178
+ dev_kfree_skb_any(skb);
1179
+}
1180
+
1181
+static int ath10k_htc_pktlog_connect(struct ath10k *ar)
1182
+{
1183
+ struct ath10k_htc_svc_conn_resp conn_resp;
1184
+ struct ath10k_htc_svc_conn_req conn_req;
1185
+ int status;
1186
+
1187
+ memset(&conn_req, 0, sizeof(conn_req));
1188
+ memset(&conn_resp, 0, sizeof(conn_resp));
1189
+
1190
+ conn_req.ep_ops.ep_tx_complete = NULL;
1191
+ conn_req.ep_ops.ep_rx_complete = ath10k_htc_pktlog_process_rx;
1192
+ conn_req.ep_ops.ep_tx_credits = NULL;
1193
+
1194
+ /* connect to control service */
1195
+ conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_LOG_MSG;
1196
+ status = ath10k_htc_connect_service(&ar->htc, &conn_req, &conn_resp);
1197
+ if (status) {
1198
+ ath10k_warn(ar, "failed to connect to PKTLOG service: %d\n",
1199
+ status);
1200
+ return status;
1201
+ }
1202
+
1203
+ return 0;
1204
+}
1205
+
1206
+static bool ath10k_htc_pktlog_svc_supported(struct ath10k *ar)
1207
+{
1208
+ u8 ul_pipe_id;
1209
+ u8 dl_pipe_id;
1210
+ int status;
1211
+
1212
+ status = ath10k_hif_map_service_to_pipe(ar, ATH10K_HTC_SVC_ID_HTT_LOG_MSG,
1213
+ &ul_pipe_id,
1214
+ &dl_pipe_id);
1215
+ if (status) {
1216
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "unsupported HTC pktlog service id: %d\n",
1217
+ ATH10K_HTC_SVC_ID_HTT_LOG_MSG);
1218
+
1219
+ return false;
1220
+ }
1221
+
1222
+ return true;
1223
+}
1224
+
8411225 int ath10k_htc_start(struct ath10k_htc *htc)
8421226 {
8431227 struct ath10k *ar = htc->ar;
....@@ -871,6 +1255,14 @@
8711255 return status;
8721256 }
8731257
1258
+ if (ath10k_htc_pktlog_svc_supported(ar)) {
1259
+ status = ath10k_htc_pktlog_connect(ar);
1260
+ if (status) {
1261
+ ath10k_err(ar, "failed to connect to pktlog: %d\n", status);
1262
+ return status;
1263
+ }
1264
+ }
1265
+
8741266 return 0;
8751267 }
8761268