Lines Matching +full:shadow +full:- +full:interrupts
1 // SPDX-License-Identifier: BSD-3-Clause-Clear
3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
12 /* CE0: host->target HTC control and raw streams */
21 /* CE1: target->host HTT + HTC control */
30 /* CE2: target->host WMI */
39 /* CE3: host->target WMI (mac0) */
48 /* CE4: host->target HTT */
56 /* CE5: target->host pktlog */
73 /* CE7: host->target WMI (mac1) */
90 /* CE9: host->target WMI (mac2) */
99 /* CE10: target->host HTT */
118 /* CE0: host->target HTC control and raw streams */
126 /* CE1: target->host HTT + HTC control */
135 /* CE2: target->host WMI */
144 /* CE3: host->target WMI (mac0) */
153 /* CE4: host->target HTT */
161 /* CE5: target->host pktlog */
178 /* CE7: host->target WMI (mac1) */
198 /* CE0: host->target HTC control and raw streams */
206 /* CE1: target->host HTT + HTC control */
215 /* CE2: target->host WMI */
224 /* CE3: host->target WMI (mac0) */
233 /* CE4: host->target HTT */
241 /* CE5: target->host pktlog */
253 /* only ce4 needs shadow workaround */ in ath11k_ce_need_shadow_fix()
263 if (!ab->hw_params.supports_shadow_regs) in ath11k_ce_stop_shadow_timers()
266 for (i = 0; i < ab->hw_params.ce_count; i++) in ath11k_ce_stop_shadow_timers()
268 ath11k_dp_shadow_stop_timer(ab, &ab->ce.hp_timer[i]); in ath11k_ce_stop_shadow_timers()
274 struct ath11k_base *ab = pipe->ab; in ath11k_ce_rx_buf_enqueue_pipe()
275 struct ath11k_ce_ring *ring = pipe->dest_ring; in ath11k_ce_rx_buf_enqueue_pipe()
278 unsigned int nentries_mask = ring->nentries_mask; in ath11k_ce_rx_buf_enqueue_pipe()
282 lockdep_assert_held(&ab->ce.ce_lock); in ath11k_ce_rx_buf_enqueue_pipe()
284 write_index = ring->write_index; in ath11k_ce_rx_buf_enqueue_pipe()
286 srng = &ab->hal.srng_list[ring->hal_ring_id]; in ath11k_ce_rx_buf_enqueue_pipe()
288 spin_lock_bh(&srng->lock); in ath11k_ce_rx_buf_enqueue_pipe()
293 ret = -ENOSPC; in ath11k_ce_rx_buf_enqueue_pipe()
299 ret = -ENOSPC; in ath11k_ce_rx_buf_enqueue_pipe()
305 ring->skb[write_index] = skb; in ath11k_ce_rx_buf_enqueue_pipe()
307 ring->write_index = write_index; in ath11k_ce_rx_buf_enqueue_pipe()
309 pipe->rx_buf_needed--; in ath11k_ce_rx_buf_enqueue_pipe()
315 spin_unlock_bh(&srng->lock); in ath11k_ce_rx_buf_enqueue_pipe()
322 struct ath11k_base *ab = pipe->ab; in ath11k_ce_rx_post_pipe()
327 if (!(pipe->dest_ring || pipe->status_ring)) in ath11k_ce_rx_post_pipe()
330 spin_lock_bh(&ab->ce.ce_lock); in ath11k_ce_rx_post_pipe()
331 while (pipe->rx_buf_needed) { in ath11k_ce_rx_post_pipe()
332 skb = dev_alloc_skb(pipe->buf_sz); in ath11k_ce_rx_post_pipe()
334 ret = -ENOMEM; in ath11k_ce_rx_post_pipe()
338 WARN_ON_ONCE(!IS_ALIGNED((unsigned long)skb->data, 4)); in ath11k_ce_rx_post_pipe()
340 paddr = dma_map_single(ab->dev, skb->data, in ath11k_ce_rx_post_pipe()
341 skb->len + skb_tailroom(skb), in ath11k_ce_rx_post_pipe()
343 if (unlikely(dma_mapping_error(ab->dev, paddr))) { in ath11k_ce_rx_post_pipe()
346 ret = -EIO; in ath11k_ce_rx_post_pipe()
350 ATH11K_SKB_RXCB(skb)->paddr = paddr; in ath11k_ce_rx_post_pipe()
356 dma_unmap_single(ab->dev, paddr, in ath11k_ce_rx_post_pipe()
357 skb->len + skb_tailroom(skb), in ath11k_ce_rx_post_pipe()
365 spin_unlock_bh(&ab->ce.ce_lock); in ath11k_ce_rx_post_pipe()
372 struct ath11k_base *ab = pipe->ab; in ath11k_ce_completed_recv_next()
379 spin_lock_bh(&ab->ce.ce_lock); in ath11k_ce_completed_recv_next()
381 sw_index = pipe->dest_ring->sw_index; in ath11k_ce_completed_recv_next()
382 nentries_mask = pipe->dest_ring->nentries_mask; in ath11k_ce_completed_recv_next()
384 srng = &ab->hal.srng_list[pipe->status_ring->hal_ring_id]; in ath11k_ce_completed_recv_next()
386 spin_lock_bh(&srng->lock); in ath11k_ce_completed_recv_next()
392 ret = -EIO; in ath11k_ce_completed_recv_next()
398 ret = -EIO; in ath11k_ce_completed_recv_next()
402 *skb = pipe->dest_ring->skb[sw_index]; in ath11k_ce_completed_recv_next()
403 pipe->dest_ring->skb[sw_index] = NULL; in ath11k_ce_completed_recv_next()
406 pipe->dest_ring->sw_index = sw_index; in ath11k_ce_completed_recv_next()
408 pipe->rx_buf_needed++; in ath11k_ce_completed_recv_next()
412 spin_unlock_bh(&srng->lock); in ath11k_ce_completed_recv_next()
414 spin_unlock_bh(&ab->ce.ce_lock); in ath11k_ce_completed_recv_next()
421 struct ath11k_base *ab = pipe->ab; in ath11k_ce_recv_process_cb()
429 max_nbytes = skb->len + skb_tailroom(skb); in ath11k_ce_recv_process_cb()
430 dma_unmap_single(ab->dev, ATH11K_SKB_RXCB(skb)->paddr, in ath11k_ce_recv_process_cb()
446 pipe->pipe_num, skb->len); in ath11k_ce_recv_process_cb()
447 pipe->recv_cb(ab, skb); in ath11k_ce_recv_process_cb()
451 if (ret && ret != -ENOSPC) { in ath11k_ce_recv_process_cb()
453 pipe->pipe_num, ret); in ath11k_ce_recv_process_cb()
454 mod_timer(&ab->rx_replenish_retry, in ath11k_ce_recv_process_cb()
461 struct ath11k_base *ab = pipe->ab; in ath11k_ce_completed_send_next()
468 spin_lock_bh(&ab->ce.ce_lock); in ath11k_ce_completed_send_next()
470 sw_index = pipe->src_ring->sw_index; in ath11k_ce_completed_send_next()
471 nentries_mask = pipe->src_ring->nentries_mask; in ath11k_ce_completed_send_next()
473 srng = &ab->hal.srng_list[pipe->src_ring->hal_ring_id]; in ath11k_ce_completed_send_next()
475 spin_lock_bh(&srng->lock); in ath11k_ce_completed_send_next()
481 skb = ERR_PTR(-EIO); in ath11k_ce_completed_send_next()
485 skb = pipe->src_ring->skb[sw_index]; in ath11k_ce_completed_send_next()
487 pipe->src_ring->skb[sw_index] = NULL; in ath11k_ce_completed_send_next()
490 pipe->src_ring->sw_index = sw_index; in ath11k_ce_completed_send_next()
493 spin_unlock_bh(&srng->lock); in ath11k_ce_completed_send_next()
495 spin_unlock_bh(&ab->ce.ce_lock); in ath11k_ce_completed_send_next()
502 struct ath11k_base *ab = pipe->ab; in ath11k_ce_tx_process_cb()
511 dma_unmap_single(ab->dev, ATH11K_SKB_CB(skb)->paddr, skb->len, in ath11k_ce_tx_process_cb()
514 if ((!pipe->send_cb) || ab->hw_params.credit_flow) { in ath11k_ce_tx_process_cb()
524 pipe->pipe_num, skb->len); in ath11k_ce_tx_process_cb()
525 pipe->send_cb(ab, skb); in ath11k_ce_tx_process_cb()
549 ring_params->msi_addr = addr_lo; in ath11k_ce_srng_msi_ring_params_setup()
550 ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32); in ath11k_ce_srng_msi_ring_params_setup()
551 ring_params->msi_data = (msi_data_idx % msi_data_count) + msi_data_start; in ath11k_ce_srng_msi_ring_params_setup()
552 ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR; in ath11k_ce_srng_msi_ring_params_setup()
562 params.ring_base_paddr = ce_ring->base_addr_ce_space; in ath11k_ce_init_ring()
563 params.ring_base_vaddr = ce_ring->base_addr_owner_space; in ath11k_ce_init_ring()
564 params.num_entries = ce_ring->nentries; in ath11k_ce_init_ring()
566 if (!(CE_ATTR_DIS_INTR & ab->hw_params.host_ce_config[ce_id].flags)) in ath11k_ce_init_ring()
571 if (!(CE_ATTR_DIS_INTR & ab->hw_params.host_ce_config[ce_id].flags)) in ath11k_ce_init_ring()
575 params.max_buffer_len = ab->hw_params.host_ce_config[ce_id].src_sz_max; in ath11k_ce_init_ring()
576 if (!(ab->hw_params.host_ce_config[ce_id].flags & CE_ATTR_DIS_INTR)) { in ath11k_ce_init_ring()
579 params.low_threshold = ce_ring->nentries - 3; in ath11k_ce_init_ring()
583 if (!(ab->hw_params.host_ce_config[ce_id].flags & CE_ATTR_DIS_INTR)) { in ath11k_ce_init_ring()
590 return -EINVAL; in ath11k_ce_init_ring()
602 ce_ring->hal_ring_id = ret; in ath11k_ce_init_ring()
604 if (ab->hw_params.supports_shadow_regs && in ath11k_ce_init_ring()
606 ath11k_dp_shadow_init_timer(ab, &ab->ce.hp_timer[ce_id], in ath11k_ce_init_ring()
608 ce_ring->hal_ring_id); in ath11k_ce_init_ring()
621 return ERR_PTR(-ENOMEM); in ath11k_ce_alloc_ring()
623 ce_ring->nentries = nentries; in ath11k_ce_alloc_ring()
624 ce_ring->nentries_mask = nentries - 1; in ath11k_ce_alloc_ring()
629 ce_ring->base_addr_owner_space_unaligned = in ath11k_ce_alloc_ring()
630 dma_alloc_coherent(ab->dev, in ath11k_ce_alloc_ring()
633 if (!ce_ring->base_addr_owner_space_unaligned) { in ath11k_ce_alloc_ring()
635 return ERR_PTR(-ENOMEM); in ath11k_ce_alloc_ring()
638 ce_ring->base_addr_ce_space_unaligned = base_addr; in ath11k_ce_alloc_ring()
640 ce_ring->base_addr_owner_space = PTR_ALIGN( in ath11k_ce_alloc_ring()
641 ce_ring->base_addr_owner_space_unaligned, in ath11k_ce_alloc_ring()
643 ce_ring->base_addr_ce_space = ALIGN( in ath11k_ce_alloc_ring()
644 ce_ring->base_addr_ce_space_unaligned, in ath11k_ce_alloc_ring()
652 struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id]; in ath11k_ce_alloc_pipe()
653 const struct ce_attr *attr = &ab->hw_params.host_ce_config[ce_id]; in ath11k_ce_alloc_pipe()
658 pipe->attr_flags = attr->flags; in ath11k_ce_alloc_pipe()
660 if (attr->src_nentries) { in ath11k_ce_alloc_pipe()
661 pipe->send_cb = attr->send_cb; in ath11k_ce_alloc_pipe()
662 nentries = roundup_pow_of_two(attr->src_nentries); in ath11k_ce_alloc_pipe()
667 pipe->src_ring = ring; in ath11k_ce_alloc_pipe()
670 if (attr->dest_nentries) { in ath11k_ce_alloc_pipe()
671 pipe->recv_cb = attr->recv_cb; in ath11k_ce_alloc_pipe()
672 nentries = roundup_pow_of_two(attr->dest_nentries); in ath11k_ce_alloc_pipe()
677 pipe->dest_ring = ring; in ath11k_ce_alloc_pipe()
683 pipe->status_ring = ring; in ath11k_ce_alloc_pipe()
691 struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id]; in ath11k_ce_per_engine_service()
692 const struct ce_attr *attr = &ab->hw_params.host_ce_config[ce_id]; in ath11k_ce_per_engine_service()
694 if (attr->src_nentries) in ath11k_ce_per_engine_service()
697 if (pipe->recv_cb) in ath11k_ce_per_engine_service()
703 struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[pipe_id]; in ath11k_ce_poll_send_completed()
704 const struct ce_attr *attr = &ab->hw_params.host_ce_config[pipe_id]; in ath11k_ce_poll_send_completed()
706 if ((pipe->attr_flags & CE_ATTR_DIS_INTR) && attr->src_nentries) in ath11k_ce_poll_send_completed()
714 struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[pipe_id]; in ath11k_ce_send()
724 * the CE has interrupts disabled and the used entries is more than the in ath11k_ce_send()
727 if (pipe->attr_flags & CE_ATTR_DIS_INTR) { in ath11k_ce_send()
728 spin_lock_bh(&ab->ce.ce_lock); in ath11k_ce_send()
729 write_index = pipe->src_ring->write_index; in ath11k_ce_send()
731 sw_index = pipe->src_ring->sw_index; in ath11k_ce_send()
734 num_used = write_index - sw_index; in ath11k_ce_send()
736 num_used = pipe->src_ring->nentries - sw_index + in ath11k_ce_send()
739 spin_unlock_bh(&ab->ce.ce_lock); in ath11k_ce_send()
742 ath11k_ce_poll_send_completed(ab, pipe->pipe_num); in ath11k_ce_send()
745 if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags)) in ath11k_ce_send()
746 return -ESHUTDOWN; in ath11k_ce_send()
748 spin_lock_bh(&ab->ce.ce_lock); in ath11k_ce_send()
750 write_index = pipe->src_ring->write_index; in ath11k_ce_send()
751 nentries_mask = pipe->src_ring->nentries_mask; in ath11k_ce_send()
753 srng = &ab->hal.srng_list[pipe->src_ring->hal_ring_id]; in ath11k_ce_send()
755 spin_lock_bh(&srng->lock); in ath11k_ce_send()
761 ret = -ENOBUFS; in ath11k_ce_send()
768 ret = -ENOBUFS; in ath11k_ce_send()
772 if (pipe->attr_flags & CE_ATTR_BYTE_SWAP_DATA) in ath11k_ce_send()
775 ath11k_hal_ce_src_set_desc(desc, ATH11K_SKB_CB(skb)->paddr, in ath11k_ce_send()
776 skb->len, transfer_id, byte_swap_data); in ath11k_ce_send()
778 pipe->src_ring->skb[write_index] = skb; in ath11k_ce_send()
779 pipe->src_ring->write_index = CE_RING_IDX_INCR(nentries_mask, in ath11k_ce_send()
785 ath11k_dp_shadow_start_timer(ab, srng, &ab->ce.hp_timer[pipe_id]); in ath11k_ce_send()
787 spin_unlock_bh(&srng->lock); in ath11k_ce_send()
789 spin_unlock_bh(&ab->ce.ce_lock); in ath11k_ce_send()
794 spin_unlock_bh(&srng->lock); in ath11k_ce_send()
796 spin_unlock_bh(&ab->ce.ce_lock); in ath11k_ce_send()
803 struct ath11k_base *ab = pipe->ab; in ath11k_ce_rx_pipe_cleanup()
804 struct ath11k_ce_ring *ring = pipe->dest_ring; in ath11k_ce_rx_pipe_cleanup()
808 if (!(ring && pipe->buf_sz)) in ath11k_ce_rx_pipe_cleanup()
811 for (i = 0; i < ring->nentries; i++) { in ath11k_ce_rx_pipe_cleanup()
812 skb = ring->skb[i]; in ath11k_ce_rx_pipe_cleanup()
816 ring->skb[i] = NULL; in ath11k_ce_rx_pipe_cleanup()
817 dma_unmap_single(ab->dev, ATH11K_SKB_RXCB(skb)->paddr, in ath11k_ce_rx_pipe_cleanup()
818 skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); in ath11k_ce_rx_pipe_cleanup()
827 for (i = 0; i < ab->hw_params.ce_count; i++) { in ath11k_ce_shadow_config()
828 if (ab->hw_params.host_ce_config[i].src_nentries) in ath11k_ce_shadow_config()
832 if (ab->hw_params.host_ce_config[i].dest_nentries) { in ath11k_ce_shadow_config()
845 if (!ab->hw_params.supports_shadow_regs) in ath11k_ce_get_shadow_config()
850 /* shadow is already configured */ in ath11k_ce_get_shadow_config()
854 /* shadow isn't configured yet, configure now. in ath11k_ce_get_shadow_config()
855 * non-CE srngs are configured firstly, then in ath11k_ce_get_shadow_config()
861 /* get the shadow configuration */ in ath11k_ce_get_shadow_config()
873 for (pipe_num = 0; pipe_num < ab->hw_params.ce_count; pipe_num++) { in ath11k_ce_cleanup_pipes()
874 pipe = &ab->ce.ce_pipe[pipe_num]; in ath11k_ce_cleanup_pipes()
877 /* Cleanup any src CE's which have interrupts disabled */ in ath11k_ce_cleanup_pipes()
891 for (i = 0; i < ab->hw_params.ce_count; i++) { in ath11k_ce_rx_post_buf()
892 pipe = &ab->ce.ce_pipe[i]; in ath11k_ce_rx_post_buf()
895 if (ret == -ENOSPC) in ath11k_ce_rx_post_buf()
900 mod_timer(&ab->rx_replenish_retry, in ath11k_ce_rx_post_buf()
922 for (i = 0; i < ab->hw_params.ce_count; i++) { in ath11k_ce_init_pipes()
923 pipe = &ab->ce.ce_pipe[i]; in ath11k_ce_init_pipes()
925 if (pipe->src_ring) { in ath11k_ce_init_pipes()
926 ret = ath11k_ce_init_ring(ab, pipe->src_ring, i, in ath11k_ce_init_pipes()
935 pipe->src_ring->write_index = 0; in ath11k_ce_init_pipes()
936 pipe->src_ring->sw_index = 0; in ath11k_ce_init_pipes()
939 if (pipe->dest_ring) { in ath11k_ce_init_pipes()
940 ret = ath11k_ce_init_ring(ab, pipe->dest_ring, i, in ath11k_ce_init_pipes()
949 pipe->rx_buf_needed = pipe->dest_ring->nentries ? in ath11k_ce_init_pipes()
950 pipe->dest_ring->nentries - 2 : 0; in ath11k_ce_init_pipes()
952 pipe->dest_ring->write_index = 0; in ath11k_ce_init_pipes()
953 pipe->dest_ring->sw_index = 0; in ath11k_ce_init_pipes()
956 if (pipe->status_ring) { in ath11k_ce_init_pipes()
957 ret = ath11k_ce_init_ring(ab, pipe->status_ring, i, in ath11k_ce_init_pipes()
966 pipe->status_ring->write_index = 0; in ath11k_ce_init_pipes()
967 pipe->status_ring->sw_index = 0; in ath11k_ce_init_pipes()
981 for (i = 0; i < ab->hw_params.ce_count; i++) { in ath11k_ce_free_pipes()
982 pipe = &ab->ce.ce_pipe[i]; in ath11k_ce_free_pipes()
985 ath11k_dp_shadow_stop_timer(ab, &ab->ce.hp_timer[i]); in ath11k_ce_free_pipes()
987 if (pipe->src_ring) { in ath11k_ce_free_pipes()
989 ce_ring = pipe->src_ring; in ath11k_ce_free_pipes()
990 dma_free_coherent(ab->dev, in ath11k_ce_free_pipes()
991 pipe->src_ring->nentries * desc_sz + in ath11k_ce_free_pipes()
993 ce_ring->base_addr_owner_space_unaligned, in ath11k_ce_free_pipes()
994 ce_ring->base_addr_ce_space_unaligned); in ath11k_ce_free_pipes()
995 kfree(pipe->src_ring); in ath11k_ce_free_pipes()
996 pipe->src_ring = NULL; in ath11k_ce_free_pipes()
999 if (pipe->dest_ring) { in ath11k_ce_free_pipes()
1001 ce_ring = pipe->dest_ring; in ath11k_ce_free_pipes()
1002 dma_free_coherent(ab->dev, in ath11k_ce_free_pipes()
1003 pipe->dest_ring->nentries * desc_sz + in ath11k_ce_free_pipes()
1005 ce_ring->base_addr_owner_space_unaligned, in ath11k_ce_free_pipes()
1006 ce_ring->base_addr_ce_space_unaligned); in ath11k_ce_free_pipes()
1007 kfree(pipe->dest_ring); in ath11k_ce_free_pipes()
1008 pipe->dest_ring = NULL; in ath11k_ce_free_pipes()
1011 if (pipe->status_ring) { in ath11k_ce_free_pipes()
1014 ce_ring = pipe->status_ring; in ath11k_ce_free_pipes()
1015 dma_free_coherent(ab->dev, in ath11k_ce_free_pipes()
1016 pipe->status_ring->nentries * desc_sz + in ath11k_ce_free_pipes()
1018 ce_ring->base_addr_owner_space_unaligned, in ath11k_ce_free_pipes()
1019 ce_ring->base_addr_ce_space_unaligned); in ath11k_ce_free_pipes()
1020 kfree(pipe->status_ring); in ath11k_ce_free_pipes()
1021 pipe->status_ring = NULL; in ath11k_ce_free_pipes()
1034 spin_lock_init(&ab->ce.ce_lock); in ath11k_ce_alloc_pipes()
1036 for (i = 0; i < ab->hw_params.ce_count; i++) { in ath11k_ce_alloc_pipes()
1037 attr = &ab->hw_params.host_ce_config[i]; in ath11k_ce_alloc_pipes()
1038 pipe = &ab->ce.ce_pipe[i]; in ath11k_ce_alloc_pipes()
1039 pipe->pipe_num = i; in ath11k_ce_alloc_pipes()
1040 pipe->ab = ab; in ath11k_ce_alloc_pipes()
1041 pipe->buf_sz = attr->src_sz_max; in ath11k_ce_alloc_pipes()
1084 if (ce_id >= ab->hw_params.ce_count) in ath11k_ce_get_attr_flags()
1085 return -EINVAL; in ath11k_ce_get_attr_flags()
1087 return ab->hw_params.host_ce_config[ce_id].flags; in ath11k_ce_get_attr_flags()