Lines Matching +full:rx +full:- +full:status +full:- +full:len
1 // SPDX-License-Identifier: ISC
3 * Copyright (c) 2005-2011 Atheros Communications Inc.
4 * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
35 WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb"); in ath10k_htc_build_tx_ctrl_skb()
49 if (htc->ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) in ath10k_htc_restore_tx_skb()
50 dma_unmap_single(htc->ar->dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); in ath10k_htc_restore_tx_skb()
57 struct ath10k *ar = ep->htc->ar; in ath10k_htc_notify_tx_completion()
61 ep->eid, skb); in ath10k_htc_notify_tx_completion()
68 if (ar->hw_params.delay_unmap_buffer && in ath10k_htc_notify_tx_completion()
69 ep->ul_pipe_id == 3) in ath10k_htc_notify_tx_completion()
72 hdr = (struct ath10k_htc_hdr *)skb->data; in ath10k_htc_notify_tx_completion()
73 ath10k_htc_restore_tx_skb(ep->htc, skb); in ath10k_htc_notify_tx_completion()
75 if (!ep->ep_ops.ep_tx_complete) { in ath10k_htc_notify_tx_completion()
76 ath10k_warn(ar, "no tx handler for eid %d\n", ep->eid); in ath10k_htc_notify_tx_completion()
81 if (hdr->flags & ATH10K_HTC_FLAG_SEND_BUNDLE) { in ath10k_htc_notify_tx_completion()
86 ep->ep_ops.ep_tx_complete(ep->htc->ar, skb); in ath10k_htc_notify_tx_completion()
95 hdr = (struct ath10k_htc_hdr *)skb->data; in ath10k_htc_prepare_tx_skb()
98 hdr->eid = ep->eid; in ath10k_htc_prepare_tx_skb()
99 hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr)); in ath10k_htc_prepare_tx_skb()
100 hdr->flags = 0; in ath10k_htc_prepare_tx_skb()
101 if (ep->tx_credit_flow_enabled && !ep->bundle_tx) in ath10k_htc_prepare_tx_skb()
102 hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE; in ath10k_htc_prepare_tx_skb()
104 spin_lock_bh(&ep->htc->tx_lock); in ath10k_htc_prepare_tx_skb()
105 hdr->seq_no = ep->seq_no++; in ath10k_htc_prepare_tx_skb()
106 spin_unlock_bh(&ep->htc->tx_lock); in ath10k_htc_prepare_tx_skb()
110 unsigned int len, in ath10k_htc_consume_credit() argument
113 struct ath10k_htc *htc = ep->htc; in ath10k_htc_consume_credit()
114 struct ath10k *ar = htc->ar; in ath10k_htc_consume_credit()
115 enum ath10k_htc_ep_id eid = ep->eid; in ath10k_htc_consume_credit()
118 if (!ep->tx_credit_flow_enabled) in ath10k_htc_consume_credit()
121 credits = DIV_ROUND_UP(len, ep->tx_credit_size); in ath10k_htc_consume_credit()
122 spin_lock_bh(&htc->tx_lock); in ath10k_htc_consume_credit()
124 if (ep->tx_credits < credits) { in ath10k_htc_consume_credit()
127 eid, credits, ep->tx_credits, consume); in ath10k_htc_consume_credit()
128 ret = -EAGAIN; in ath10k_htc_consume_credit()
133 ep->tx_credits -= credits; in ath10k_htc_consume_credit()
136 eid, credits, ep->tx_credits); in ath10k_htc_consume_credit()
140 spin_unlock_bh(&htc->tx_lock); in ath10k_htc_consume_credit()
144 static void ath10k_htc_release_credit(struct ath10k_htc_ep *ep, unsigned int len) in ath10k_htc_release_credit() argument
146 struct ath10k_htc *htc = ep->htc; in ath10k_htc_release_credit()
147 struct ath10k *ar = htc->ar; in ath10k_htc_release_credit()
148 enum ath10k_htc_ep_id eid = ep->eid; in ath10k_htc_release_credit()
151 if (!ep->tx_credit_flow_enabled) in ath10k_htc_release_credit()
154 credits = DIV_ROUND_UP(len, ep->tx_credit_size); in ath10k_htc_release_credit()
155 spin_lock_bh(&htc->tx_lock); in ath10k_htc_release_credit()
156 ep->tx_credits += credits; in ath10k_htc_release_credit()
159 eid, credits, ep->tx_credits); in ath10k_htc_release_credit()
160 spin_unlock_bh(&htc->tx_lock); in ath10k_htc_release_credit()
162 if (ep->ep_ops.ep_tx_credits) in ath10k_htc_release_credit()
163 ep->ep_ops.ep_tx_credits(htc->ar); in ath10k_htc_release_credit()
170 struct ath10k *ar = htc->ar; in ath10k_htc_send()
171 struct ath10k_htc_ep *ep = &htc->endpoint[eid]; in ath10k_htc_send()
174 struct device *dev = htc->ar->dev; in ath10k_htc_send()
178 if (htc->ar->state == ATH10K_STATE_WEDGED) in ath10k_htc_send()
179 return -ECOMM; in ath10k_htc_send()
183 return -ENOENT; in ath10k_htc_send()
188 skb_len = skb->len; in ath10k_htc_send()
195 skb_cb->eid = eid; in ath10k_htc_send()
196 if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) { in ath10k_htc_send()
197 skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, in ath10k_htc_send()
199 ret = dma_mapping_error(dev, skb_cb->paddr); in ath10k_htc_send()
201 ret = -EIO; in ath10k_htc_send()
206 sg_item.transfer_id = ep->eid; in ath10k_htc_send()
208 sg_item.vaddr = skb->data; in ath10k_htc_send()
209 sg_item.paddr = skb_cb->paddr; in ath10k_htc_send()
210 sg_item.len = skb->len; in ath10k_htc_send()
212 ret = ath10k_hif_tx_sg(htc->ar, ep->ul_pipe_id, &sg_item, 1); in ath10k_htc_send()
219 if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) in ath10k_htc_send()
220 dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); in ath10k_htc_send()
230 struct ath10k_htc *htc = &ar->htc; in ath10k_htc_tx_completion_handler()
238 ep = &htc->endpoint[skb_cb->eid]; in ath10k_htc_tx_completion_handler()
252 int len, in ath10k_htc_process_credit_report() argument
255 struct ath10k *ar = htc->ar; in ath10k_htc_process_credit_report()
259 if (len % sizeof(*report)) in ath10k_htc_process_credit_report()
260 ath10k_warn(ar, "Uneven credit report len %d", len); in ath10k_htc_process_credit_report()
262 n_reports = len / sizeof(*report); in ath10k_htc_process_credit_report()
264 spin_lock_bh(&htc->tx_lock); in ath10k_htc_process_credit_report()
266 if (report->eid >= ATH10K_HTC_EP_COUNT) in ath10k_htc_process_credit_report()
269 ep = &htc->endpoint[report->eid]; in ath10k_htc_process_credit_report()
270 ep->tx_credits += report->credits; in ath10k_htc_process_credit_report()
273 report->eid, report->credits, ep->tx_credits); in ath10k_htc_process_credit_report()
275 if (ep->ep_ops.ep_tx_credits) { in ath10k_htc_process_credit_report()
276 spin_unlock_bh(&htc->tx_lock); in ath10k_htc_process_credit_report()
277 ep->ep_ops.ep_tx_credits(htc->ar); in ath10k_htc_process_credit_report()
278 spin_lock_bh(&htc->tx_lock); in ath10k_htc_process_credit_report()
281 spin_unlock_bh(&htc->tx_lock); in ath10k_htc_process_credit_report()
287 int len, in ath10k_htc_process_lookahead() argument
292 struct ath10k *ar = htc->ar; in ath10k_htc_process_lookahead()
299 if (report->pre_valid != ((~report->post_valid) & 0xFF)) in ath10k_htc_process_lookahead()
304 "htc rx lookahead found pre_valid 0x%x post_valid 0x%x\n", in ath10k_htc_process_lookahead()
305 report->pre_valid, report->post_valid); in ath10k_htc_process_lookahead()
308 memcpy((u8 *)next_lookaheads, report->lookahead, 4); in ath10k_htc_process_lookahead()
319 int len, in ath10k_htc_process_lookahead_bundle() argument
324 struct ath10k *ar = htc->ar; in ath10k_htc_process_lookahead_bundle()
325 int bundle_cnt = len / sizeof(*report); in ath10k_htc_process_lookahead_bundle()
327 if (!bundle_cnt || (bundle_cnt > htc->max_msgs_per_htc_bundle)) { in ath10k_htc_process_lookahead_bundle()
330 return -EINVAL; in ath10k_htc_process_lookahead_bundle()
338 report->lookahead, 4); in ath10k_htc_process_lookahead_bundle()
356 struct ath10k *ar = htc->ar; in ath10k_htc_process_trailer()
357 int status = 0; in ath10k_htc_process_trailer() local
361 size_t len; in ath10k_htc_process_trailer() local
369 if (length < sizeof(record->hdr)) { in ath10k_htc_process_trailer()
370 status = -EINVAL; in ath10k_htc_process_trailer()
374 if (record->hdr.len > length) { in ath10k_htc_process_trailer()
377 record->hdr.len); in ath10k_htc_process_trailer()
378 status = -EINVAL; in ath10k_htc_process_trailer()
382 switch (record->hdr.id) { in ath10k_htc_process_trailer()
384 len = sizeof(struct ath10k_htc_credit_report); in ath10k_htc_process_trailer()
385 if (record->hdr.len < len) { in ath10k_htc_process_trailer()
387 status = -EINVAL; in ath10k_htc_process_trailer()
391 record->credit_report, in ath10k_htc_process_trailer()
392 record->hdr.len, in ath10k_htc_process_trailer()
396 len = sizeof(struct ath10k_htc_lookahead_report); in ath10k_htc_process_trailer()
397 if (record->hdr.len < len) { in ath10k_htc_process_trailer()
399 status = -EINVAL; in ath10k_htc_process_trailer()
402 status = ath10k_htc_process_lookahead(htc, in ath10k_htc_process_trailer()
403 record->lookahead_report, in ath10k_htc_process_trailer()
404 record->hdr.len, in ath10k_htc_process_trailer()
410 bundle = record->lookahead_bundle; in ath10k_htc_process_trailer()
411 status = ath10k_htc_process_lookahead_bundle(htc, in ath10k_htc_process_trailer()
413 record->hdr.len, in ath10k_htc_process_trailer()
420 record->hdr.id, record->hdr.len); in ath10k_htc_process_trailer()
424 if (status) in ath10k_htc_process_trailer()
428 buffer += sizeof(record->hdr) + record->hdr.len; in ath10k_htc_process_trailer()
429 length -= sizeof(record->hdr) + record->hdr.len; in ath10k_htc_process_trailer()
432 if (status) in ath10k_htc_process_trailer()
433 ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc rx bad trailer", "", in ath10k_htc_process_trailer()
436 return status; in ath10k_htc_process_trailer()
442 int status = 0; in ath10k_htc_rx_completion_handler() local
443 struct ath10k_htc *htc = &ar->htc; in ath10k_htc_rx_completion_handler()
452 hdr = (struct ath10k_htc_hdr *)skb->data; in ath10k_htc_rx_completion_handler()
455 eid = hdr->eid; in ath10k_htc_rx_completion_handler()
458 ath10k_warn(ar, "HTC Rx: invalid eid %d\n", eid); in ath10k_htc_rx_completion_handler()
464 ep = &htc->endpoint[eid]; in ath10k_htc_rx_completion_handler()
465 if (ep->service_id == ATH10K_HTC_SVC_ID_UNUSED) { in ath10k_htc_rx_completion_handler()
466 ath10k_warn(ar, "htc rx endpoint %d is not connected\n", eid); in ath10k_htc_rx_completion_handler()
470 payload_len = __le16_to_cpu(hdr->len); in ath10k_htc_rx_completion_handler()
473 ath10k_warn(ar, "HTC rx frame too long, len: %zu\n", in ath10k_htc_rx_completion_handler()
475 ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", "", in ath10k_htc_rx_completion_handler()
480 if (skb->len < payload_len) { in ath10k_htc_rx_completion_handler()
482 "HTC Rx: insufficient length, got %d, expected %d\n", in ath10k_htc_rx_completion_handler()
483 skb->len, payload_len); in ath10k_htc_rx_completion_handler()
484 ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", in ath10k_htc_rx_completion_handler()
490 trailer_present = hdr->flags & ATH10K_HTC_FLAG_TRAILER_PRESENT; in ath10k_htc_rx_completion_handler()
494 trailer_len = hdr->trailer_len; in ath10k_htc_rx_completion_handler()
507 trailer -= trailer_len; in ath10k_htc_rx_completion_handler()
508 status = ath10k_htc_process_trailer(htc, trailer, in ath10k_htc_rx_completion_handler()
509 trailer_len, hdr->eid, in ath10k_htc_rx_completion_handler()
511 if (status) in ath10k_htc_rx_completion_handler()
514 skb_trim(skb, skb->len - trailer_len); in ath10k_htc_rx_completion_handler()
517 if (((int)payload_len - (int)trailer_len) <= 0) in ath10k_htc_rx_completion_handler()
521 ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %p\n", in ath10k_htc_rx_completion_handler()
523 ep->ep_ops.ep_rx_complete(ar, skb); in ath10k_htc_rx_completion_handler()
525 /* skb is now owned by the rx completion handler */ in ath10k_htc_rx_completion_handler()
535 struct ath10k_htc *htc = &ar->htc; in ath10k_htc_control_rx_complete()
536 struct ath10k_htc_msg *msg = (struct ath10k_htc_msg *)skb->data; in ath10k_htc_control_rx_complete()
538 switch (__le16_to_cpu(msg->hdr.message_id)) { in ath10k_htc_control_rx_complete()
542 if (completion_done(&htc->ctl_resp)) { in ath10k_htc_control_rx_complete()
546 ath10k_warn(ar, "HTC rx ctrl still processing\n"); in ath10k_htc_control_rx_complete()
547 complete(&htc->ctl_resp); in ath10k_htc_control_rx_complete()
551 htc->control_resp_len = in ath10k_htc_control_rx_complete()
552 min_t(int, skb->len, in ath10k_htc_control_rx_complete()
555 memcpy(htc->control_resp_buffer, skb->data, in ath10k_htc_control_rx_complete()
556 htc->control_resp_len); in ath10k_htc_control_rx_complete()
558 complete(&htc->ctl_resp); in ath10k_htc_control_rx_complete()
561 htc->htc_ops.target_send_suspend_complete(ar); in ath10k_htc_control_rx_complete()
618 ep = &htc->endpoint[i]; in ath10k_htc_reset_endpoint_states()
619 ep->service_id = ATH10K_HTC_SVC_ID_UNUSED; in ath10k_htc_reset_endpoint_states()
620 ep->max_ep_message_len = 0; in ath10k_htc_reset_endpoint_states()
621 ep->max_tx_queue_depth = 0; in ath10k_htc_reset_endpoint_states()
622 ep->eid = i; in ath10k_htc_reset_endpoint_states()
623 ep->htc = htc; in ath10k_htc_reset_endpoint_states()
624 ep->tx_credit_flow_enabled = true; in ath10k_htc_reset_endpoint_states()
637 allocation = htc->total_transmit_credits; in ath10k_htc_get_credit_allocation()
647 struct ath10k_htc *htc = ep->htc; in ath10k_htc_send_bundle()
648 struct ath10k *ar = htc->ar; in ath10k_htc_send_bundle()
653 ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle skb len %d\n", bundle_skb->len); in ath10k_htc_send_bundle()
654 skb_len = bundle_skb->len; in ath10k_htc_send_bundle()
658 sg_item.transfer_id = ep->eid; in ath10k_htc_send_bundle()
660 sg_item.vaddr = bundle_skb->data; in ath10k_htc_send_bundle()
661 sg_item.len = bundle_skb->len; in ath10k_htc_send_bundle()
663 ret = ath10k_hif_tx_sg(htc->ar, ep->ul_pipe_id, &sg_item, 1); in ath10k_htc_send_bundle()
674 skb_queue_head(&ep->tx_req_head, skb); in ath10k_htc_send_bundle()
676 skb_queue_tail(&ep->tx_complete_head, skb); in ath10k_htc_send_bundle()
681 queue_work(ar->workqueue_tx_complete, &ar->tx_complete_work); in ath10k_htc_send_bundle()
684 "bundle tx status %d eid %d req count %d count %d len %d\n", in ath10k_htc_send_bundle()
685 ret, ep->eid, skb_queue_len(&ep->tx_req_head), cn, skb_len); in ath10k_htc_send_bundle()
691 struct ath10k_htc *htc = ep->htc; in ath10k_htc_send_one_skb()
692 struct ath10k *ar = htc->ar; in ath10k_htc_send_one_skb()
695 ret = ath10k_htc_send(htc, ep->eid, skb); in ath10k_htc_send_one_skb()
698 skb_queue_head(&ep->tx_req_head, skb); in ath10k_htc_send_one_skb()
700 ath10k_dbg(ar, ATH10K_DBG_HTC, "tx one status %d eid %d len %d pending count %d\n", in ath10k_htc_send_one_skb()
701 ret, ep->eid, skb->len, skb_queue_len(&ep->tx_req_head)); in ath10k_htc_send_one_skb()
706 struct ath10k_htc *htc = ep->htc; in ath10k_htc_send_bundle_skbs()
713 if (htc->ar->state == ATH10K_STATE_WEDGED) in ath10k_htc_send_bundle_skbs()
714 return -ECOMM; in ath10k_htc_send_bundle_skbs()
716 if (ep->tx_credit_flow_enabled && in ath10k_htc_send_bundle_skbs()
717 ep->tx_credits < ATH10K_MIN_CREDIT_PER_HTC_TX_BUNDLE) in ath10k_htc_send_bundle_skbs()
720 bundles_left = ATH10K_MAX_MSG_PER_HTC_TX_BUNDLE * ep->tx_credit_size; in ath10k_htc_send_bundle_skbs()
724 return -ENOMEM; in ath10k_htc_send_bundle_skbs()
726 bundle_buf = bundle_skb->data; in ath10k_htc_send_bundle_skbs()
730 skb = skb_dequeue(&ep->tx_req_head); in ath10k_htc_send_bundle_skbs()
735 trans_len = skb->len + sizeof(*hdr); in ath10k_htc_send_bundle_skbs()
736 credit_remainder = trans_len % ep->tx_credit_size; in ath10k_htc_send_bundle_skbs()
739 credit_pad = ep->tx_credit_size - credit_remainder; in ath10k_htc_send_bundle_skbs()
744 bundle_buf + trans_len - bundle_skb->data, in ath10k_htc_send_bundle_skbs()
747 skb_queue_head(&ep->tx_req_head, skb); in ath10k_htc_send_bundle_skbs()
752 bundle_skb->len = bundle_buf - bundle_skb->data; in ath10k_htc_send_bundle_skbs()
756 skb_queue_head(&ep->tx_req_head, skb); in ath10k_htc_send_bundle_skbs()
760 if (skb_queue_len(&ep->tx_req_head) == 0) { in ath10k_htc_send_bundle_skbs()
765 if (ep->tx_credit_flow_enabled && in ath10k_htc_send_bundle_skbs()
766 ep->tx_credits < ATH10K_MIN_CREDIT_PER_HTC_TX_BUNDLE) { in ath10k_htc_send_bundle_skbs()
767 skb_queue_head(&ep->tx_req_head, skb); in ath10k_htc_send_bundle_skbs()
772 ATH10K_MAX_MSG_PER_HTC_TX_BUNDLE * ep->tx_credit_size; in ath10k_htc_send_bundle_skbs()
776 skb_queue_head(&ep->tx_req_head, skb); in ath10k_htc_send_bundle_skbs()
777 return -ENOMEM; in ath10k_htc_send_bundle_skbs()
779 bundle_buf = bundle_skb->data; in ath10k_htc_send_bundle_skbs()
786 memcpy(bundle_buf, skb->data, skb->len); in ath10k_htc_send_bundle_skbs()
788 hdr->flags |= ATH10K_HTC_FLAG_SEND_BUNDLE; in ath10k_htc_send_bundle_skbs()
789 hdr->pad_len = __cpu_to_le16(credit_pad); in ath10k_htc_send_bundle_skbs()
791 bundles_left -= trans_len; in ath10k_htc_send_bundle_skbs()
795 if (bundle_buf != bundle_skb->data) { in ath10k_htc_send_bundle_skbs()
796 bundle_skb->len = bundle_buf - bundle_skb->data; in ath10k_htc_send_bundle_skbs()
812 for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) { in ath10k_htc_bundle_tx_work()
813 ep = &ar->htc.endpoint[i]; in ath10k_htc_bundle_tx_work()
815 if (!ep->bundle_tx) in ath10k_htc_bundle_tx_work()
819 ep->eid, skb_queue_len(&ep->tx_req_head)); in ath10k_htc_bundle_tx_work()
821 if (skb_queue_len(&ep->tx_req_head) >= in ath10k_htc_bundle_tx_work()
825 skb = skb_dequeue(&ep->tx_req_head); in ath10k_htc_bundle_tx_work()
842 for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) { in ath10k_htc_tx_complete_work()
843 ep = &ar->htc.endpoint[i]; in ath10k_htc_tx_complete_work()
844 eid = ep->eid; in ath10k_htc_tx_complete_work()
845 if (ep->bundle_tx && eid == ar->htt.eid) { in ath10k_htc_tx_complete_work()
847 ep->eid, skb_queue_len(&ep->tx_complete_head)); in ath10k_htc_tx_complete_work()
850 skb = skb_dequeue(&ep->tx_complete_head); in ath10k_htc_tx_complete_work()
863 struct ath10k_htc_ep *ep = &htc->endpoint[eid]; in ath10k_htc_send_hl()
864 struct ath10k *ar = htc->ar; in ath10k_htc_send_hl()
866 if (sizeof(struct ath10k_htc_hdr) + skb->len > ep->tx_credit_size) { in ath10k_htc_send_hl()
867 ath10k_dbg(ar, ATH10K_DBG_HTC, "tx exceed max len %d\n", skb->len); in ath10k_htc_send_hl()
868 return -ENOMEM; in ath10k_htc_send_hl()
871 ath10k_dbg(ar, ATH10K_DBG_HTC, "htc send hl eid %d bundle %d tx count %d len %d\n", in ath10k_htc_send_hl()
872 eid, ep->bundle_tx, skb_queue_len(&ep->tx_req_head), skb->len); in ath10k_htc_send_hl()
874 if (ep->bundle_tx) { in ath10k_htc_send_hl()
875 skb_queue_tail(&ep->tx_req_head, skb); in ath10k_htc_send_hl()
876 queue_work(ar->workqueue, &ar->bundle_tx_work); in ath10k_htc_send_hl()
885 if (ep->htc->max_msgs_per_htc_bundle >= ATH10K_MIN_MSG_PER_HTC_TX_BUNDLE && in ath10k_htc_setup_tx_req()
886 !ep->bundle_tx) { in ath10k_htc_setup_tx_req()
887 ep->bundle_tx = true; in ath10k_htc_setup_tx_req()
888 skb_queue_head_init(&ep->tx_req_head); in ath10k_htc_setup_tx_req()
889 skb_queue_head_init(&ep->tx_complete_head); in ath10k_htc_setup_tx_req()
898 cancel_work_sync(&ar->bundle_tx_work); in ath10k_htc_stop_hl()
899 cancel_work_sync(&ar->tx_complete_work); in ath10k_htc_stop_hl()
901 for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) { in ath10k_htc_stop_hl()
902 ep = &ar->htc.endpoint[i]; in ath10k_htc_stop_hl()
904 if (!ep->bundle_tx) in ath10k_htc_stop_hl()
908 ep->eid, skb_queue_len(&ep->tx_req_head)); in ath10k_htc_stop_hl()
910 skb_queue_purge(&ep->tx_req_head); in ath10k_htc_stop_hl()
916 struct ath10k *ar = htc->ar; in ath10k_htc_wait_target()
917 int i, status = 0; in ath10k_htc_wait_target() local
922 time_left = wait_for_completion_timeout(&htc->ctl_resp, in ath10k_htc_wait_target()
929 * properly in KVM PCI-passthrough sometimes. in ath10k_htc_wait_target()
934 ath10k_hif_send_complete_check(htc->ar, i, 1); in ath10k_htc_wait_target()
937 wait_for_completion_timeout(&htc->ctl_resp, in ath10k_htc_wait_target()
941 status = -ETIMEDOUT; in ath10k_htc_wait_target()
944 if (status < 0) { in ath10k_htc_wait_target()
945 ath10k_err(ar, "ctl_resp never came in (%d)\n", status); in ath10k_htc_wait_target()
946 return status; in ath10k_htc_wait_target()
949 if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) { in ath10k_htc_wait_target()
950 ath10k_err(ar, "Invalid HTC ready msg len:%d\n", in ath10k_htc_wait_target()
951 htc->control_resp_len); in ath10k_htc_wait_target()
952 return -ECOMM; in ath10k_htc_wait_target()
955 msg = (struct ath10k_htc_msg *)htc->control_resp_buffer; in ath10k_htc_wait_target()
956 message_id = __le16_to_cpu(msg->hdr.message_id); in ath10k_htc_wait_target()
960 return -ECOMM; in ath10k_htc_wait_target()
963 if (ar->hw_params.use_fw_tx_credits) in ath10k_htc_wait_target()
964 htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count); in ath10k_htc_wait_target()
966 htc->total_transmit_credits = 1; in ath10k_htc_wait_target()
968 htc->target_credit_size = __le16_to_cpu(msg->ready.credit_size); in ath10k_htc_wait_target()
972 htc->total_transmit_credits, in ath10k_htc_wait_target()
973 htc->target_credit_size, in ath10k_htc_wait_target()
974 msg->ready.credit_count); in ath10k_htc_wait_target()
976 if ((htc->total_transmit_credits == 0) || in ath10k_htc_wait_target()
977 (htc->target_credit_size == 0)) { in ath10k_htc_wait_target()
979 return -ECOMM; in ath10k_htc_wait_target()
985 if (htc->control_resp_len >= in ath10k_htc_wait_target()
986 sizeof(msg->hdr) + sizeof(msg->ready_ext)) { in ath10k_htc_wait_target()
987 htc->alt_data_credit_size = in ath10k_htc_wait_target()
988 __le16_to_cpu(msg->ready_ext.reserved) & in ath10k_htc_wait_target()
990 htc->max_msgs_per_htc_bundle = in ath10k_htc_wait_target()
991 min_t(u8, msg->ready_ext.max_msgs_per_htc_bundle, in ath10k_htc_wait_target()
994 "Extended ready message RX bundle size %d alt size %d\n", in ath10k_htc_wait_target()
995 htc->max_msgs_per_htc_bundle, in ath10k_htc_wait_target()
996 htc->alt_data_credit_size); in ath10k_htc_wait_target()
999 INIT_WORK(&ar->bundle_tx_work, ath10k_htc_bundle_tx_work); in ath10k_htc_wait_target()
1000 INIT_WORK(&ar->tx_complete_work, ath10k_htc_tx_complete_work); in ath10k_htc_wait_target()
1009 struct ath10k *ar = htc->ar; in ath10k_htc_change_tx_credit_flow()
1010 struct ath10k_htc_ep *ep = &ar->htc.endpoint[eid]; in ath10k_htc_change_tx_credit_flow()
1012 ep->tx_credit_flow_enabled = enable; in ath10k_htc_change_tx_credit_flow()
1019 struct ath10k *ar = htc->ar; in ath10k_htc_connect_service()
1028 int length, status; in ath10k_htc_connect_service() local
1035 if (conn_req->service_id == ATH10K_HTC_SVC_ID_RSVD_CTRL) { in ath10k_htc_connect_service()
1044 conn_req->service_id); in ath10k_htc_connect_service()
1048 htc_service_name(conn_req->service_id)); in ath10k_htc_connect_service()
1050 skb = ath10k_htc_build_tx_ctrl_skb(htc->ar); in ath10k_htc_connect_service()
1053 return -ENOMEM; in ath10k_htc_connect_service()
1056 length = sizeof(msg->hdr) + sizeof(msg->connect_service); in ath10k_htc_connect_service()
1058 memset(skb->data, 0, length); in ath10k_htc_connect_service()
1060 msg = (struct ath10k_htc_msg *)skb->data; in ath10k_htc_connect_service()
1061 msg->hdr.message_id = in ath10k_htc_connect_service()
1067 if (conn_req->service_id != ATH10K_HTC_SVC_ID_WMI_CONTROL) { in ath10k_htc_connect_service()
1072 req_msg = &msg->connect_service; in ath10k_htc_connect_service()
1073 req_msg->flags = __cpu_to_le16(flags); in ath10k_htc_connect_service()
1074 req_msg->service_id = __cpu_to_le16(conn_req->service_id); in ath10k_htc_connect_service()
1076 reinit_completion(&htc->ctl_resp); in ath10k_htc_connect_service()
1078 status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb); in ath10k_htc_connect_service()
1079 if (status) { in ath10k_htc_connect_service()
1081 return status; in ath10k_htc_connect_service()
1085 time_left = wait_for_completion_timeout(&htc->ctl_resp, in ath10k_htc_connect_service()
1089 return -ETIMEDOUT; in ath10k_htc_connect_service()
1093 msg = (struct ath10k_htc_msg *)htc->control_resp_buffer; in ath10k_htc_connect_service()
1094 resp_msg = &msg->connect_service_response; in ath10k_htc_connect_service()
1095 message_id = __le16_to_cpu(msg->hdr.message_id); in ath10k_htc_connect_service()
1096 service_id = __le16_to_cpu(resp_msg->service_id); in ath10k_htc_connect_service()
1099 (htc->control_resp_len < sizeof(msg->hdr) + in ath10k_htc_connect_service()
1100 sizeof(msg->connect_service_response))) { in ath10k_htc_connect_service()
1102 return -EPROTO; in ath10k_htc_connect_service()
1106 "HTC Service %s connect response: status: 0x%x, assigned ep: 0x%x\n", in ath10k_htc_connect_service()
1108 resp_msg->status, resp_msg->eid); in ath10k_htc_connect_service()
1110 conn_resp->connect_resp_code = resp_msg->status; in ath10k_htc_connect_service()
1112 /* check response status */ in ath10k_htc_connect_service()
1113 if (resp_msg->status != ATH10K_HTC_CONN_SVC_STATUS_SUCCESS) { in ath10k_htc_connect_service()
1116 resp_msg->status); in ath10k_htc_connect_service()
1117 return -EPROTO; in ath10k_htc_connect_service()
1120 assigned_eid = (enum ath10k_htc_ep_id)resp_msg->eid; in ath10k_htc_connect_service()
1121 max_msg_size = __le16_to_cpu(resp_msg->max_msg_size); in ath10k_htc_connect_service()
1126 return -EPROTO; in ath10k_htc_connect_service()
1129 return -EPROTO; in ath10k_htc_connect_service()
1131 ep = &htc->endpoint[assigned_eid]; in ath10k_htc_connect_service()
1132 ep->eid = assigned_eid; in ath10k_htc_connect_service()
1134 if (ep->service_id != ATH10K_HTC_SVC_ID_UNUSED) in ath10k_htc_connect_service()
1135 return -EPROTO; in ath10k_htc_connect_service()
1138 conn_resp->eid = assigned_eid; in ath10k_htc_connect_service()
1139 conn_resp->max_msg_len = __le16_to_cpu(resp_msg->max_msg_size); in ath10k_htc_connect_service()
1142 ep->service_id = conn_req->service_id; in ath10k_htc_connect_service()
1143 ep->max_tx_queue_depth = conn_req->max_send_queue_depth; in ath10k_htc_connect_service()
1144 ep->max_ep_message_len = __le16_to_cpu(resp_msg->max_msg_size); in ath10k_htc_connect_service()
1145 ep->tx_credits = tx_alloc; in ath10k_htc_connect_service()
1146 ep->tx_credit_size = htc->target_credit_size; in ath10k_htc_connect_service()
1148 if (conn_req->service_id == ATH10K_HTC_SVC_ID_HTT_DATA_MSG && in ath10k_htc_connect_service()
1149 htc->alt_data_credit_size != 0) in ath10k_htc_connect_service()
1150 ep->tx_credit_size = htc->alt_data_credit_size; in ath10k_htc_connect_service()
1153 ep->ep_ops = conn_req->ep_ops; in ath10k_htc_connect_service()
1155 status = ath10k_hif_map_service_to_pipe(htc->ar, in ath10k_htc_connect_service()
1156 ep->service_id, in ath10k_htc_connect_service()
1157 &ep->ul_pipe_id, in ath10k_htc_connect_service()
1158 &ep->dl_pipe_id); in ath10k_htc_connect_service()
1159 if (status) { in ath10k_htc_connect_service()
1161 ep->service_id); in ath10k_htc_connect_service()
1162 return status; in ath10k_htc_connect_service()
1167 htc_service_name(ep->service_id), ep->ul_pipe_id, in ath10k_htc_connect_service()
1168 ep->dl_pipe_id, ep->eid); in ath10k_htc_connect_service()
1170 if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) { in ath10k_htc_connect_service()
1171 ep->tx_credit_flow_enabled = false; in ath10k_htc_connect_service()
1174 htc_service_name(ep->service_id), assigned_eid); in ath10k_htc_connect_service()
1177 return status; in ath10k_htc_connect_service()
1190 /* FW/HTC requires 4-byte aligned streams */ in ath10k_htc_alloc_skb()
1191 if (!IS_ALIGNED((unsigned long)skb->data, 4)) in ath10k_htc_alloc_skb()
1199 trace_ath10k_htt_pktlog(ar, skb->data, skb->len); in ath10k_htc_pktlog_process_rx()
1207 int status; in ath10k_htc_pktlog_connect() local
1218 status = ath10k_htc_connect_service(&ar->htc, &conn_req, &conn_resp); in ath10k_htc_pktlog_connect()
1219 if (status) { in ath10k_htc_pktlog_connect()
1221 status); in ath10k_htc_pktlog_connect()
1222 return status; in ath10k_htc_pktlog_connect()
1232 int status; in ath10k_htc_pktlog_svc_supported() local
1234 status = ath10k_hif_map_service_to_pipe(ar, ATH10K_HTC_SVC_ID_HTT_LOG_MSG, in ath10k_htc_pktlog_svc_supported()
1237 if (status) { in ath10k_htc_pktlog_svc_supported()
1249 struct ath10k *ar = htc->ar; in ath10k_htc_start()
1251 int status = 0; in ath10k_htc_start() local
1254 skb = ath10k_htc_build_tx_ctrl_skb(htc->ar); in ath10k_htc_start()
1256 return -ENOMEM; in ath10k_htc_start()
1258 skb_put(skb, sizeof(msg->hdr) + sizeof(msg->setup_complete_ext)); in ath10k_htc_start()
1259 memset(skb->data, 0, skb->len); in ath10k_htc_start()
1261 msg = (struct ath10k_htc_msg *)skb->data; in ath10k_htc_start()
1262 msg->hdr.message_id = in ath10k_htc_start()
1265 if (ar->hif.bus == ATH10K_BUS_SDIO) { in ath10k_htc_start()
1267 msg->setup_complete_ext.flags = in ath10k_htc_start()
1269 msg->setup_complete_ext.max_msgs_per_bundled_recv = in ath10k_htc_start()
1270 htc->max_msgs_per_htc_bundle; in ath10k_htc_start()
1274 status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb); in ath10k_htc_start()
1275 if (status) { in ath10k_htc_start()
1277 return status; in ath10k_htc_start()
1281 status = ath10k_htc_pktlog_connect(ar); in ath10k_htc_start()
1282 if (status) { in ath10k_htc_start()
1283 ath10k_err(ar, "failed to connect to pktlog: %d\n", status); in ath10k_htc_start()
1284 return status; in ath10k_htc_start()
1294 int status; in ath10k_htc_init() local
1295 struct ath10k_htc *htc = &ar->htc; in ath10k_htc_init()
1299 spin_lock_init(&htc->tx_lock); in ath10k_htc_init()
1303 htc->ar = ar; in ath10k_htc_init()
1314 status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp); in ath10k_htc_init()
1315 if (status) { in ath10k_htc_init()
1317 status); in ath10k_htc_init()
1318 return status; in ath10k_htc_init()
1321 init_completion(&htc->ctl_resp); in ath10k_htc_init()