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 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()
251 struct ath12k_htc *htc = &ab->htc; in ath12k_htc_rx_completion_handler()
260 hdr = (struct ath12k_htc_hdr *)skb->data; in ath12k_htc_rx_completion_handler()
263 eid = le32_get_bits(hdr->htc_info, HTC_HDR_ENDPOINTID); in ath12k_htc_rx_completion_handler()
270 ep = &htc->endpoint[eid]; in ath12k_htc_rx_completion_handler()
272 payload_len = le32_get_bits(hdr->htc_info, HTC_HDR_PAYLOADLEN); in ath12k_htc_rx_completion_handler()
280 if (skb->len < payload_len) { in ath12k_htc_rx_completion_handler()
282 skb->len, payload_len); in ath12k_htc_rx_completion_handler()
287 trailer_present = le32_get_bits(hdr->htc_info, HTC_HDR_FLAGS) & in ath12k_htc_rx_completion_handler()
293 trailer_len = le32_get_bits(hdr->ctrl_info, in ath12k_htc_rx_completion_handler()
307 trailer -= trailer_len; in ath12k_htc_rx_completion_handler()
313 skb_trim(skb, skb->len - trailer_len); in ath12k_htc_rx_completion_handler()
321 struct ath12k_htc_msg *msg = (struct ath12k_htc_msg *)skb->data; in ath12k_htc_rx_completion_handler()
323 switch (le32_get_bits(msg->msg_svc_id, HTC_MSG_MESSAGEID)) { in ath12k_htc_rx_completion_handler()
327 if (completion_done(&htc->ctl_resp)) { in ath12k_htc_rx_completion_handler()
332 complete(&htc->ctl_resp); in ath12k_htc_rx_completion_handler()
336 htc->control_resp_len = in ath12k_htc_rx_completion_handler()
337 min_t(int, skb->len, in ath12k_htc_rx_completion_handler()
340 memcpy(htc->control_resp_buffer, skb->data, in ath12k_htc_rx_completion_handler()
341 htc->control_resp_len); in ath12k_htc_rx_completion_handler()
343 complete(&htc->ctl_resp); in ath12k_htc_rx_completion_handler()
355 le32_get_bits(msg->msg_svc_id, HTC_MSG_MESSAGEID)); in ath12k_htc_rx_completion_handler()
363 ep->ep_ops.ep_rx_complete(ab, skb); in ath12k_htc_rx_completion_handler()
366 ath12k_ce_poll_send_completed(ab, ep->ul_pipe_id); in ath12k_htc_rx_completion_handler()
414 return "IPA TX"; in htc_service_name()
430 ep = &htc->endpoint[i]; in ath12k_htc_reset_endpoint_states()
431 ep->service_id = ATH12K_HTC_SVC_ID_UNUSED; in ath12k_htc_reset_endpoint_states()
432 ep->max_ep_message_len = 0; in ath12k_htc_reset_endpoint_states()
433 ep->max_tx_queue_depth = 0; in ath12k_htc_reset_endpoint_states()
434 ep->eid = i; in ath12k_htc_reset_endpoint_states()
435 ep->htc = htc; in ath12k_htc_reset_endpoint_states()
436 ep->tx_credit_flow_enabled = true; in ath12k_htc_reset_endpoint_states()
446 serv_entry = htc->service_alloc_table; in ath12k_htc_get_credit_allocation()
468 credits = htc->total_transmit_credits; in ath12k_htc_setup_target_buffer_assignments()
469 serv_entry = htc->service_alloc_table; in ath12k_htc_setup_target_buffer_assignments()
471 if ((htc->wmi_ep_count == 0) || in ath12k_htc_setup_target_buffer_assignments()
472 (htc->wmi_ep_count > ARRAY_SIZE(svc_id))) in ath12k_htc_setup_target_buffer_assignments()
473 return -EINVAL; in ath12k_htc_setup_target_buffer_assignments()
476 credits = credits / htc->wmi_ep_count; in ath12k_htc_setup_target_buffer_assignments()
477 for (i = 0; i < htc->wmi_ep_count; i++) { in ath12k_htc_setup_target_buffer_assignments()
488 struct ath12k_base *ab = htc->ab; in ath12k_htc_wait_target()
490 struct ath12k_htc_ready *ready; in ath12k_htc_wait_target() local
495 time_left = wait_for_completion_timeout(&htc->ctl_resp, in ath12k_htc_wait_target()
500 for (i = 0; i < ab->hw_params->ce_count; i++) in ath12k_htc_wait_target()
501 ath12k_ce_per_engine_service(htc->ab, i); in ath12k_htc_wait_target()
504 wait_for_completion_timeout(&htc->ctl_resp, in ath12k_htc_wait_target()
508 status = -ETIMEDOUT; in ath12k_htc_wait_target()
516 if (htc->control_resp_len < sizeof(*ready)) { in ath12k_htc_wait_target()
517 ath12k_warn(ab, "Invalid HTC ready msg len:%d\n", in ath12k_htc_wait_target()
518 htc->control_resp_len); in ath12k_htc_wait_target()
519 return -ECOMM; in ath12k_htc_wait_target()
522 ready = (struct ath12k_htc_ready *)htc->control_resp_buffer; in ath12k_htc_wait_target()
523 message_id = le32_get_bits(ready->id_credit_count, HTC_MSG_MESSAGEID); in ath12k_htc_wait_target()
524 credit_count = le32_get_bits(ready->id_credit_count, in ath12k_htc_wait_target()
526 credit_size = le32_get_bits(ready->size_ep, HTC_READY_MSG_CREDITSIZE); in ath12k_htc_wait_target()
529 ath12k_warn(ab, "Invalid HTC ready msg: 0x%x\n", message_id); in ath12k_htc_wait_target()
530 return -ECOMM; in ath12k_htc_wait_target()
533 htc->total_transmit_credits = credit_count; in ath12k_htc_wait_target()
534 htc->target_credit_size = credit_size; in ath12k_htc_wait_target()
537 "Target ready! transmit resources: %d size:%d\n", in ath12k_htc_wait_target()
538 htc->total_transmit_credits, htc->target_credit_size); in ath12k_htc_wait_target()
540 if ((htc->total_transmit_credits == 0) || in ath12k_htc_wait_target()
541 (htc->target_credit_size == 0)) { in ath12k_htc_wait_target()
543 return -ECOMM; in ath12k_htc_wait_target()
555 struct ath12k_base *ab = htc->ab; in ath12k_htc_connect_service()
570 if (conn_req->service_id == ATH12K_HTC_SVC_ID_RSVD_CTRL) { in ath12k_htc_connect_service()
575 goto setup; in ath12k_htc_connect_service()
579 conn_req->service_id); in ath12k_htc_connect_service()
583 htc_service_name(conn_req->service_id)); in ath12k_htc_connect_service()
588 return -ENOMEM; in ath12k_htc_connect_service()
593 memset(skb->data, 0, length); in ath12k_htc_connect_service()
595 req_msg = (struct ath12k_htc_conn_svc *)skb->data; in ath12k_htc_connect_service()
596 req_msg->msg_svc_id = le32_encode_bits(ATH12K_HTC_MSG_CONNECT_SERVICE_ID, in ath12k_htc_connect_service()
602 if (!(conn_req->service_id == ATH12K_HTC_SVC_ID_WMI_CONTROL || in ath12k_htc_connect_service()
603 conn_req->service_id == ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC1 || in ath12k_htc_connect_service()
604 conn_req->service_id == ATH12K_HTC_SVC_ID_WMI_CONTROL_MAC2)) { in ath12k_htc_connect_service()
609 req_msg->flags_len = le32_encode_bits(flags, HTC_SVC_MSG_CONNECTIONFLAGS); in ath12k_htc_connect_service()
610 req_msg->msg_svc_id |= le32_encode_bits(conn_req->service_id, in ath12k_htc_connect_service()
613 reinit_completion(&htc->ctl_resp); in ath12k_htc_connect_service()
622 time_left = wait_for_completion_timeout(&htc->ctl_resp, in ath12k_htc_connect_service()
626 return -ETIMEDOUT; in ath12k_htc_connect_service()
630 resp_msg = (struct ath12k_htc_conn_svc_resp *)htc->control_resp_buffer; in ath12k_htc_connect_service()
631 message_id = le32_get_bits(resp_msg->msg_svc_id, HTC_MSG_MESSAGEID); in ath12k_htc_connect_service()
632 service_id = le32_get_bits(resp_msg->msg_svc_id, in ath12k_htc_connect_service()
636 (htc->control_resp_len < sizeof(*resp_msg))) { in ath12k_htc_connect_service()
638 return -EPROTO; in ath12k_htc_connect_service()
644 le32_get_bits(resp_msg->flags_len, HTC_SVC_RESP_MSG_STATUS), in ath12k_htc_connect_service()
645 le32_get_bits(resp_msg->flags_len, HTC_SVC_RESP_MSG_ENDPOINTID)); in ath12k_htc_connect_service()
647 conn_resp->connect_resp_code = le32_get_bits(resp_msg->flags_len, in ath12k_htc_connect_service()
651 if (conn_resp->connect_resp_code != ATH12K_HTC_CONN_SVC_STATUS_SUCCESS) { in ath12k_htc_connect_service()
654 conn_resp->connect_resp_code); in ath12k_htc_connect_service()
655 return -EPROTO; in ath12k_htc_connect_service()
658 assigned_eid = le32_get_bits(resp_msg->flags_len, in ath12k_htc_connect_service()
661 max_msg_size = le32_get_bits(resp_msg->flags_len, in ath12k_htc_connect_service()
664 setup: in ath12k_htc_connect_service()
667 return -EPROTO; in ath12k_htc_connect_service()
670 return -EPROTO; in ath12k_htc_connect_service()
672 ep = &htc->endpoint[assigned_eid]; in ath12k_htc_connect_service()
673 ep->eid = assigned_eid; in ath12k_htc_connect_service()
675 if (ep->service_id != ATH12K_HTC_SVC_ID_UNUSED) in ath12k_htc_connect_service()
676 return -EPROTO; in ath12k_htc_connect_service()
679 conn_resp->eid = assigned_eid; in ath12k_htc_connect_service()
680 conn_resp->max_msg_len = le32_get_bits(resp_msg->flags_len, in ath12k_htc_connect_service()
683 /* setup the endpoint */ in ath12k_htc_connect_service()
684 ep->service_id = conn_req->service_id; in ath12k_htc_connect_service()
685 ep->max_tx_queue_depth = conn_req->max_send_queue_depth; in ath12k_htc_connect_service()
686 ep->max_ep_message_len = le32_get_bits(resp_msg->flags_len, in ath12k_htc_connect_service()
688 ep->tx_credits = tx_alloc; in ath12k_htc_connect_service()
691 ep->ep_ops = conn_req->ep_ops; in ath12k_htc_connect_service()
693 status = ath12k_hif_map_service_to_pipe(htc->ab, in ath12k_htc_connect_service()
694 ep->service_id, in ath12k_htc_connect_service()
695 &ep->ul_pipe_id, in ath12k_htc_connect_service()
696 &ep->dl_pipe_id); in ath12k_htc_connect_service()
701 "boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n", in ath12k_htc_connect_service()
702 htc_service_name(ep->service_id), ep->ul_pipe_id, in ath12k_htc_connect_service()
703 ep->dl_pipe_id, ep->eid); in ath12k_htc_connect_service()
705 if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) { in ath12k_htc_connect_service()
706 ep->tx_credit_flow_enabled = false; in ath12k_htc_connect_service()
709 htc_service_name(ep->service_id), assigned_eid); in ath12k_htc_connect_service()
719 struct ath12k_base *ab = htc->ab; in ath12k_htc_start()
724 return -ENOMEM; in ath12k_htc_start()
727 memset(skb->data, 0, skb->len); in ath12k_htc_start()
729 msg = (struct ath12k_htc_setup_complete_extended *)skb->data; in ath12k_htc_start()
730 msg->msg_id = le32_encode_bits(ATH12K_HTC_MSG_SETUP_COMPLETE_EX_ID, in ath12k_htc_start()
746 struct ath12k_htc *htc = &ab->htc; in ath12k_htc_init()
751 spin_lock_init(&htc->tx_lock); in ath12k_htc_init()
755 htc->ab = ab; in ath12k_htc_init()
757 switch (ab->wmi_ab.preferred_hw_mode) { in ath12k_htc_init()
759 htc->wmi_ep_count = 1; in ath12k_htc_init()
763 htc->wmi_ep_count = 2; in ath12k_htc_init()
766 htc->wmi_ep_count = 3; in ath12k_htc_init()
769 htc->wmi_ep_count = ab->hw_params->max_radios; in ath12k_htc_init()
773 /* setup our pseudo HTC control endpoint connection */ in ath12k_htc_init()
786 init_completion(&htc->ctl_resp); in ath12k_htc_init()