Lines Matching +full:ipa +full:- +full:setup +full:- +full:ready

1 // SPDX-License-Identifier: BSD-3-Clause-Clear
3 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4 * Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
22 /* FW/HTC requires 4-byte aligned streams */ in ath12k_htc_alloc_skb()
23 if (!IS_ALIGNED((unsigned long)skb->data, 4)) in ath12k_htc_alloc_skb()
45 WARN_ON_ONCE(!IS_ALIGNED((unsigned long)skb->data, 4)); in ath12k_htc_build_tx_ctrl_skb()
58 hdr = (struct ath12k_htc_hdr *)skb->data; in ath12k_htc_prepare_tx_skb()
61 hdr->htc_info = le32_encode_bits(ep->eid, HTC_HDR_ENDPOINTID) | in ath12k_htc_prepare_tx_skb()
62 le32_encode_bits((skb->len - sizeof(*hdr)), in ath12k_htc_prepare_tx_skb()
65 if (ep->tx_credit_flow_enabled) in ath12k_htc_prepare_tx_skb()
66 hdr->htc_info |= le32_encode_bits(ATH12K_HTC_FLAG_NEED_CREDIT_UPDATE, in ath12k_htc_prepare_tx_skb()
69 spin_lock_bh(&ep->htc->tx_lock); in ath12k_htc_prepare_tx_skb()
70 hdr->ctrl_info = le32_encode_bits(ep->seq_no++, HTC_HDR_CONTROLBYTES1); in ath12k_htc_prepare_tx_skb()
71 spin_unlock_bh(&ep->htc->tx_lock); in ath12k_htc_prepare_tx_skb()
78 struct ath12k_htc_ep *ep = &htc->endpoint[eid]; in ath12k_htc_send()
80 struct device *dev = htc->ab->dev; in ath12k_htc_send()
81 struct ath12k_base *ab = htc->ab; in ath12k_htc_send()
87 return -ENOENT; in ath12k_htc_send()
92 if (ep->tx_credit_flow_enabled) { in ath12k_htc_send()
93 credits = DIV_ROUND_UP(skb->len, htc->target_credit_size); in ath12k_htc_send()
94 spin_lock_bh(&htc->tx_lock); in ath12k_htc_send()
95 if (ep->tx_credits < credits) { in ath12k_htc_send()
98 eid, credits, ep->tx_credits); in ath12k_htc_send()
99 spin_unlock_bh(&htc->tx_lock); in ath12k_htc_send()
100 ret = -EAGAIN; in ath12k_htc_send()
103 ep->tx_credits -= credits; in ath12k_htc_send()
106 eid, credits, ep->tx_credits); in ath12k_htc_send()
107 spin_unlock_bh(&htc->tx_lock); in ath12k_htc_send()
112 skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE); in ath12k_htc_send()
113 ret = dma_mapping_error(dev, skb_cb->paddr); in ath12k_htc_send()
115 ret = -EIO; in ath12k_htc_send()
119 ret = ath12k_ce_send(htc->ab, skb, ep->ul_pipe_id, ep->eid); in ath12k_htc_send()
126 dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE); in ath12k_htc_send()
128 if (ep->tx_credit_flow_enabled) { in ath12k_htc_send()
129 spin_lock_bh(&htc->tx_lock); in ath12k_htc_send()
130 ep->tx_credits += credits; in ath12k_htc_send()
133 eid, credits, ep->tx_credits); in ath12k_htc_send()
134 spin_unlock_bh(&htc->tx_lock); in ath12k_htc_send()
136 if (ep->ep_ops.ep_tx_credits) in ath12k_htc_send()
137 ep->ep_ops.ep_tx_credits(htc->ab); in ath12k_htc_send()
150 struct ath12k_base *ab = htc->ab; in ath12k_htc_process_credit_report()
159 spin_lock_bh(&htc->tx_lock); in ath12k_htc_process_credit_report()
161 if (report->eid >= ATH12K_HTC_EP_COUNT) in ath12k_htc_process_credit_report()
164 ep = &htc->endpoint[report->eid]; in ath12k_htc_process_credit_report()
165 ep->tx_credits += report->credits; in ath12k_htc_process_credit_report()
168 report->eid, report->credits, ep->tx_credits); in ath12k_htc_process_credit_report()
170 if (ep->ep_ops.ep_tx_credits) { in ath12k_htc_process_credit_report()
171 spin_unlock_bh(&htc->tx_lock); in ath12k_htc_process_credit_report()
172 ep->ep_ops.ep_tx_credits(htc->ab); in ath12k_htc_process_credit_report()
173 spin_lock_bh(&htc->tx_lock); in ath12k_htc_process_credit_report()
176 spin_unlock_bh(&htc->tx_lock); in ath12k_htc_process_credit_report()
184 struct ath12k_base *ab = htc->ab; in ath12k_htc_process_trailer()
192 if (length < sizeof(record->hdr)) { in ath12k_htc_process_trailer()
193 status = -EINVAL; in ath12k_htc_process_trailer()
197 if (record->hdr.len > length) { in ath12k_htc_process_trailer()
200 record->hdr.len); in ath12k_htc_process_trailer()
201 status = -EINVAL; in ath12k_htc_process_trailer()
205 switch (record->hdr.id) { in ath12k_htc_process_trailer()
208 if (record->hdr.len < len) { in ath12k_htc_process_trailer()
210 status = -EINVAL; in ath12k_htc_process_trailer()
214 record->credit_report, in ath12k_htc_process_trailer()
215 record->hdr.len, in ath12k_htc_process_trailer()
220 record->hdr.id, record->hdr.len); in ath12k_htc_process_trailer()
228 buffer += sizeof(record->hdr) + record->hdr.len; in ath12k_htc_process_trailer()
229 length -= sizeof(record->hdr) + record->hdr.len; in ath12k_htc_process_trailer()
240 set_bit(ATH12K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags); in ath12k_htc_suspend_complete()
242 clear_bit(ATH12K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags); in ath12k_htc_suspend_complete()
244 complete(&ab->htc_suspend); in ath12k_htc_suspend_complete()
256 struct ath12k_htc *htc = &ab->htc; in ath12k_htc_rx_completion_handler()
265 hdr = (struct ath12k_htc_hdr *)skb->data; in ath12k_htc_rx_completion_handler()
268 eid = le32_get_bits(hdr->htc_info, HTC_HDR_ENDPOINTID); in ath12k_htc_rx_completion_handler()
275 ep = &htc->endpoint[eid]; in ath12k_htc_rx_completion_handler()
277 payload_len = le32_get_bits(hdr->htc_info, HTC_HDR_PAYLOADLEN); in ath12k_htc_rx_completion_handler()
285 if (skb->len < payload_len) { in ath12k_htc_rx_completion_handler()
287 skb->len, payload_len); in ath12k_htc_rx_completion_handler()
292 trailer_present = le32_get_bits(hdr->htc_info, HTC_HDR_FLAGS) & in ath12k_htc_rx_completion_handler()
298 trailer_len = le32_get_bits(hdr->ctrl_info, in ath12k_htc_rx_completion_handler()
312 trailer -= trailer_len; in ath12k_htc_rx_completion_handler()
318 skb_trim(skb, skb->len - trailer_len); in ath12k_htc_rx_completion_handler()
326 struct ath12k_htc_msg *msg = (struct ath12k_htc_msg *)skb->data; in ath12k_htc_rx_completion_handler()
328 switch (le32_get_bits(msg->msg_svc_id, HTC_MSG_MESSAGEID)) { in ath12k_htc_rx_completion_handler()
332 if (completion_done(&htc->ctl_resp)) { in ath12k_htc_rx_completion_handler()
337 complete(&htc->ctl_resp); in ath12k_htc_rx_completion_handler()
341 htc->control_resp_len = in ath12k_htc_rx_completion_handler()
342 min_t(int, skb->len, in ath12k_htc_rx_completion_handler()
345 memcpy(htc->control_resp_buffer, skb->data, in ath12k_htc_rx_completion_handler()
346 htc->control_resp_len); in ath12k_htc_rx_completion_handler()
348 complete(&htc->ctl_resp); in ath12k_htc_rx_completion_handler()
361 le32_get_bits(msg->msg_svc_id, HTC_MSG_MESSAGEID)); in ath12k_htc_rx_completion_handler()
369 ep->ep_ops.ep_rx_complete(ab, skb); in ath12k_htc_rx_completion_handler()
372 ath12k_ce_poll_send_completed(ab, ep->ul_pipe_id); in ath12k_htc_rx_completion_handler()
420 return "IPA TX"; in htc_service_name()
436 ep = &htc->endpoint[i]; in ath12k_htc_reset_endpoint_states()
437 ep->service_id = ATH12K_HTC_SVC_ID_UNUSED; in ath12k_htc_reset_endpoint_states()
438 ep->max_ep_message_len = 0; in ath12k_htc_reset_endpoint_states()
439 ep->max_tx_queue_depth = 0; in ath12k_htc_reset_endpoint_states()
440 ep->eid = i; in ath12k_htc_reset_endpoint_states()
441 ep->htc = htc; in ath12k_htc_reset_endpoint_states()
442 ep->tx_credit_flow_enabled = true; in ath12k_htc_reset_endpoint_states()
452 serv_entry = htc->service_alloc_table; in ath12k_htc_get_credit_allocation()
474 credits = htc->total_transmit_credits; in ath12k_htc_setup_target_buffer_assignments()
475 serv_entry = htc->service_alloc_table; in ath12k_htc_setup_target_buffer_assignments()
477 if ((htc->wmi_ep_count == 0) || in ath12k_htc_setup_target_buffer_assignments()
478 (htc->wmi_ep_count > ARRAY_SIZE(svc_id))) in ath12k_htc_setup_target_buffer_assignments()
479 return -EINVAL; in ath12k_htc_setup_target_buffer_assignments()
482 credits = credits / htc->wmi_ep_count; in ath12k_htc_setup_target_buffer_assignments()
483 for (i = 0; i < htc->wmi_ep_count; i++) { in ath12k_htc_setup_target_buffer_assignments()
494 struct ath12k_base *ab = htc->ab; in ath12k_htc_wait_target()
496 struct ath12k_htc_ready *ready; in ath12k_htc_wait_target() local
501 time_left = wait_for_completion_timeout(&htc->ctl_resp, in ath12k_htc_wait_target()
506 for (i = 0; i < ab->hw_params->ce_count; i++) in ath12k_htc_wait_target()
507 ath12k_ce_per_engine_service(htc->ab, i); in ath12k_htc_wait_target()
510 wait_for_completion_timeout(&htc->ctl_resp, in ath12k_htc_wait_target()
514 status = -ETIMEDOUT; in ath12k_htc_wait_target()
522 if (htc->control_resp_len < sizeof(*ready)) { in ath12k_htc_wait_target()
523 ath12k_warn(ab, "Invalid HTC ready msg len:%d\n", in ath12k_htc_wait_target()
524 htc->control_resp_len); in ath12k_htc_wait_target()
525 return -ECOMM; in ath12k_htc_wait_target()
528 ready = (struct ath12k_htc_ready *)htc->control_resp_buffer; in ath12k_htc_wait_target()
529 message_id = le32_get_bits(ready->id_credit_count, HTC_MSG_MESSAGEID); in ath12k_htc_wait_target()
530 credit_count = le32_get_bits(ready->id_credit_count, in ath12k_htc_wait_target()
532 credit_size = le32_get_bits(ready->size_ep, HTC_READY_MSG_CREDITSIZE); in ath12k_htc_wait_target()
535 ath12k_warn(ab, "Invalid HTC ready msg: 0x%x\n", message_id); in ath12k_htc_wait_target()
536 return -ECOMM; in ath12k_htc_wait_target()
539 htc->total_transmit_credits = credit_count; in ath12k_htc_wait_target()
540 htc->target_credit_size = credit_size; in ath12k_htc_wait_target()
543 "Target ready! transmit resources: %d size:%d\n", in ath12k_htc_wait_target()
544 htc->total_transmit_credits, htc->target_credit_size); in ath12k_htc_wait_target()
546 if ((htc->total_transmit_credits == 0) || in ath12k_htc_wait_target()
547 (htc->target_credit_size == 0)) { in ath12k_htc_wait_target()
549 return -ECOMM; in ath12k_htc_wait_target()
561 struct ath12k_base *ab = htc->ab; in ath12k_htc_connect_service()
576 if (conn_req->service_id == ATH12K_HTC_SVC_ID_RSVD_CTRL) { in ath12k_htc_connect_service()
581 goto setup; in ath12k_htc_connect_service()
585 conn_req->service_id); in ath12k_htc_connect_service()
589 htc_service_name(conn_req->service_id)); in ath12k_htc_connect_service()
594 return -ENOMEM; in ath12k_htc_connect_service()
599 memset(skb->data, 0, length); in ath12k_htc_connect_service()
601 req_msg = (struct ath12k_htc_conn_svc *)skb->data; in ath12k_htc_connect_service()
602 req_msg->msg_svc_id = le32_encode_bits(ATH12K_HTC_MSG_CONNECT_SERVICE_ID, in ath12k_htc_connect_service()
608 if (!(conn_req->service_id == ATH12K_HTC_SVC_ID_WMI_CONTROL || in ath12k_htc_connect_service()
609 conn_req->service_id == ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1 || in ath12k_htc_connect_service()
610 conn_req->service_id == ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC2)) { in ath12k_htc_connect_service()
615 req_msg->flags_len = le32_encode_bits(flags, HTC_SVC_MSG_CONNECTIONFLAGS); in ath12k_htc_connect_service()
616 req_msg->msg_svc_id |= le32_encode_bits(conn_req->service_id, in ath12k_htc_connect_service()
619 reinit_completion(&htc->ctl_resp); in ath12k_htc_connect_service()
628 time_left = wait_for_completion_timeout(&htc->ctl_resp, in ath12k_htc_connect_service()
632 return -ETIMEDOUT; in ath12k_htc_connect_service()
636 resp_msg = (struct ath12k_htc_conn_svc_resp *)htc->control_resp_buffer; in ath12k_htc_connect_service()
637 message_id = le32_get_bits(resp_msg->msg_svc_id, HTC_MSG_MESSAGEID); in ath12k_htc_connect_service()
638 service_id = le32_get_bits(resp_msg->msg_svc_id, in ath12k_htc_connect_service()
642 (htc->control_resp_len < sizeof(*resp_msg))) { in ath12k_htc_connect_service()
644 return -EPROTO; in ath12k_htc_connect_service()
650 le32_get_bits(resp_msg->flags_len, HTC_SVC_RESP_MSG_STATUS), in ath12k_htc_connect_service()
651 le32_get_bits(resp_msg->flags_len, HTC_SVC_RESP_MSG_ENDPOINTID)); in ath12k_htc_connect_service()
653 conn_resp->connect_resp_code = le32_get_bits(resp_msg->flags_len, in ath12k_htc_connect_service()
657 if (conn_resp->connect_resp_code != ATH12K_HTC_CONN_SVC_STATUS_SUCCESS) { in ath12k_htc_connect_service()
660 conn_resp->connect_resp_code); in ath12k_htc_connect_service()
661 return -EPROTO; in ath12k_htc_connect_service()
664 assigned_eid = le32_get_bits(resp_msg->flags_len, in ath12k_htc_connect_service()
667 max_msg_size = le32_get_bits(resp_msg->flags_len, in ath12k_htc_connect_service()
670 setup: in ath12k_htc_connect_service()
673 return -EPROTO; in ath12k_htc_connect_service()
676 return -EPROTO; in ath12k_htc_connect_service()
678 ep = &htc->endpoint[assigned_eid]; in ath12k_htc_connect_service()
679 ep->eid = assigned_eid; in ath12k_htc_connect_service()
681 if (ep->service_id != ATH12K_HTC_SVC_ID_UNUSED) in ath12k_htc_connect_service()
682 return -EPROTO; in ath12k_htc_connect_service()
685 conn_resp->eid = assigned_eid; in ath12k_htc_connect_service()
686 conn_resp->max_msg_len = le32_get_bits(resp_msg->flags_len, in ath12k_htc_connect_service()
689 /* setup the endpoint */ in ath12k_htc_connect_service()
690 ep->service_id = conn_req->service_id; in ath12k_htc_connect_service()
691 ep->max_tx_queue_depth = conn_req->max_send_queue_depth; in ath12k_htc_connect_service()
692 ep->max_ep_message_len = le32_get_bits(resp_msg->flags_len, in ath12k_htc_connect_service()
694 ep->tx_credits = tx_alloc; in ath12k_htc_connect_service()
697 ep->ep_ops = conn_req->ep_ops; in ath12k_htc_connect_service()
699 status = ath12k_hif_map_service_to_pipe(htc->ab, in ath12k_htc_connect_service()
700 ep->service_id, in ath12k_htc_connect_service()
701 &ep->ul_pipe_id, in ath12k_htc_connect_service()
702 &ep->dl_pipe_id); in ath12k_htc_connect_service()
707 "boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n", in ath12k_htc_connect_service()
708 htc_service_name(ep->service_id), ep->ul_pipe_id, in ath12k_htc_connect_service()
709 ep->dl_pipe_id, ep->eid); in ath12k_htc_connect_service()
711 if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) { in ath12k_htc_connect_service()
712 ep->tx_credit_flow_enabled = false; in ath12k_htc_connect_service()
715 htc_service_name(ep->service_id), assigned_eid); in ath12k_htc_connect_service()
725 struct ath12k_base *ab = htc->ab; in ath12k_htc_start()
730 return -ENOMEM; in ath12k_htc_start()
733 memset(skb->data, 0, skb->len); in ath12k_htc_start()
735 msg = (struct ath12k_htc_setup_complete_extended *)skb->data; in ath12k_htc_start()
736 msg->msg_id = le32_encode_bits(ATH12K_HTC_MSG_SETUP_COMPLETE_EX_ID, in ath12k_htc_start()
752 struct ath12k_htc *htc = &ab->htc; in ath12k_htc_init()
757 spin_lock_init(&htc->tx_lock); in ath12k_htc_init()
761 htc->ab = ab; in ath12k_htc_init()
763 switch (ab->wmi_ab.preferred_hw_mode) { in ath12k_htc_init()
765 htc->wmi_ep_count = 1; in ath12k_htc_init()
769 htc->wmi_ep_count = 2; in ath12k_htc_init()
772 htc->wmi_ep_count = 3; in ath12k_htc_init()
775 htc->wmi_ep_count = ab->hw_params->max_radios; in ath12k_htc_init()
779 /* setup our pseudo HTC control endpoint connection */ in ath12k_htc_init()
792 init_completion(&htc->ctl_resp); in ath12k_htc_init()