11#ifndef __INCLUDE_DAO_DMA_H__
12#define __INCLUDE_DAO_DMA_H__
16#include <rte_dmadev.h>
18#include <rte_mempool.h>
19#include <rte_prefetch.h>
22#include <dao_config.h>
27#define DAO_DMA_MAX_POINTER 15u
30#define DAO_DMA_MAX_META_POINTER 48
33#define DAO_DMA_MAX_VCHAN_PER_LCORE 64
36#define DAO_DMA_MAX_INFLIGHT_MDATA 4096
39#define DAO_DMA_DOORBELL_THRESHOLD 1024
301static __rte_always_inline
int
319static __rte_always_inline uint16_t
322 return rte_dma_burst_capacity(vchan->
devid, vchan->
vchan);
337static __rte_always_inline
bool
342 uint16_t inflight = vchan->
tail - vchan->
head;
343 uint32_t n_src, n_dst, nb_desc;
346 if (likely((src_avail >= (
int)nb_src || !vchan->
src_i) &&
347 (dst_avail >= (
int)nb_dst || !vchan->
dst_i)))
351 n_src = (nb_src + flush_thr - 1) / flush_thr;
352 n_dst = (nb_dst + flush_thr - 1) / flush_thr;
353 nb_desc = RTE_MAX(n_src, n_dst);
375static __rte_always_inline
bool
378 uint16_t head = vchan->
head;
379 uint16_t tail = vchan->
tail;
381 if (vchan->
src_i && (tail == op_idx))
384 return head <= tail ? (op_idx < head || op_idx >= tail) : (op_idx < head && op_idx >= tail);
397static __rte_always_inline
bool
402 uint64_t flags = (uint64_t)vchan->
auto_free << 3;
405 if (likely((src_avail >= (
int)avail || !vchan->
src_i) &&
406 (dst_avail >= (
int)avail || !vchan->
dst_i)))
410 flags |= RTE_DMA_OP_FLAG_SUBMIT;
413 vchan->
dst_i, flags);
414 if (unlikely(rc < 0)) {
422 if (flags & RTE_DMA_OP_FLAG_SUBMIT)
443static __rte_always_inline uint16_t
459static __rte_always_inline uint16_t
475static __rte_always_inline
struct rte_dma_sge *
489static __rte_always_inline
struct rte_dma_sge *
512static __rte_always_inline
void
516 uint16_t src_i = vchan->
src_i;
517 uint16_t dst_i = vchan->
dst_i;
519 vchan->
dst[dst_i].addr = dst;
520 vchan->
dst[dst_i].length = dst_len;
521 vchan->
src[src_i].addr = src;
522 vchan->
src[src_i].length = src_len;
524 vchan->
src_i = src_i + 1;
525 vchan->
dst_i = dst_i + 1;
541static __rte_always_inline
void
544 uint16_t dst_i = vchan->
dst_i;
546 vchan->
dst[dst_i].addr = dst;
547 vchan->
dst[dst_i].length = dst_len;
549 vchan->
dst_i = dst_i + 1;
565static __rte_always_inline
void
568 uint16_t src_i = vchan->
src_i;
570 vchan->
src[src_i].addr = src;
571 vchan->
src[src_i].length = src_len;
573 vchan->
src_i = src_i + 1;
588static __rte_always_inline uint16_t
591 struct rte_dma_sge *src, *dst;
592 uint16_t src_i = vchan->
src_i;
593 uint16_t dst_i = vchan->
dst_i;
594 int src_avail = vchan->
flush_thr - src_i;
597 src = vchan->
src + src_i;
598 dst = vchan->
dst + dst_i;
599 if (src_avail >= 4) {
600 vst1q_u64((uint64_t *)&src[0], vsrc[0]);
601 vst1q_u64((uint64_t *)&src[1], vsrc[1]);
602 vst1q_u64((uint64_t *)&src[2], vsrc[2]);
603 vst1q_u64((uint64_t *)&src[3], vsrc[3]);
605 vst1q_u64((uint64_t *)&dst[0], vdst[0]);
606 vst1q_u64((uint64_t *)&dst[1], vdst[1]);
607 vst1q_u64((uint64_t *)&dst[2], vdst[2]);
608 vst1q_u64((uint64_t *)&dst[3], vdst[3]);
610 vchan->
src_i = src_i + 4;
611 vchan->
dst_i = dst_i + 4;
616 while (i < 4 && src_avail > 0) {
617 vst1q_u64((uint64_t *)src, vsrc[i]);
618 vst1q_u64((uint64_t *)dst, vdst[i]);
624 vchan->
src_i = src_i + i;
625 vchan->
dst_i = dst_i + i;
630 src_i = vchan->
src_i;
631 dst_i = vchan->
dst_i;
632 src = vchan->
src + src_i;
633 dst = vchan->
dst + dst_i;
636 while (i < 4 && src_avail > 0) {
637 vst1q_u64((uint64_t *)src, vsrc[i]);
638 vst1q_u64((uint64_t *)dst, vdst[i]);
655static __rte_always_inline
void
662 cmpl = rte_dma_completed(vchan->
devid, vchan->
vchan, 128, NULL, &has_err);
663 if (unlikely(has_err)) {
678static __rte_always_inline uint16_t
694static __rte_always_inline
struct rte_dma_op **
711static __rte_always_inline
void
725static __rte_always_inline
void
739static __rte_always_inline
void
743 op->user_meta = (uint64_t)(uintptr_t)ptr;
744 op->event_meta = (uint64_t)(uintptr_t)pend_ptr;
745 op->rsvd = ((uint32_t)val << 16) | pend_val;
757static __rte_always_inline
void
760 uint32_t cmpl, i, j, idx = 0;
764 cmpl = rte_dma_completed(vchan->
devid, vchan->
vchan, 128, NULL, &has_err);
765 if (unlikely(has_err)) {
769 for (i = vchan->
head; i < vchan->
head + cmpl; i++) {
771 for (j = 0; j < vchan->
mdata[idx].
cnt; j++) {
773 __atomic_store_n(vchan->
mdata[idx].
ptr[j], vchan->
mdata[idx].val[j],
793static __rte_always_inline
void
798 struct rte_dma_op *deq_ops[DEQ_SZ];
804 cmpl = rte_dma_dequeue_ops(vchan->
devid, vchan->
vchan, deq_ops, DEQ_SZ);
808 for (i = 0; i < cmpl; i++) {
809 struct rte_dma_op *op = deq_ops[i];
811 if (unlikely(op->status != RTE_DMA_STATUS_SUCCESSFUL))
815 uint16_t *ptr = (uint16_t *)(uintptr_t)op->user_meta;
816 uint16_t *pend_ptr = (uint16_t *)(uintptr_t)op->event_meta;
817 uint16_t val = op->rsvd >> 16;
818 uint16_t pend_val = op->rsvd & 0xFFFF;
821 __atomic_store_n(ptr, val, __ATOMIC_RELEASE);
824 *pend_ptr -= pend_val;
850static __rte_always_inline
void
852 uint16_t *pend_ptr, uint16_t pend_val, uint16_t tail)
858 vchan->
mdata[idx].val[j] = val;
873static __rte_always_inline
void
876 uint32_t cmpl, i, j, idx = 0;
881 cmpl = rte_dma_completed(vchan->
devid, vchan->
vchan, 128, NULL, &has_err);
882 if (unlikely(has_err)) {
886 for (i = vchan->
head; i < vchan->
head + cmpl; i++) {
888 for (j = 0; j < vchan->
mdata[idx].
cnt; j++) {
889 ptr = (uint32_t *)vchan->
mdata[idx].
ptr[j];
891 __atomic_store_n(ptr, vchan->
mdata[idx].val32[j], __ATOMIC_RELEASE);
893 *ptr = vchan->
mdata[idx].val32[j];
912static __rte_always_inline
void
919 vchan->
mdata[idx].
ptr[j] = (uint16_t *)ptr;
920 vchan->
mdata[idx].val32[j] = val;
static __rte_always_inline void dao_dma_enq_src_x1(struct dao_dma_vchan_state *vchan, rte_iova_t src, uint32_t src_len)
static __rte_always_inline int dao_dma_has_stats_feature(void)
static __rte_always_inline struct rte_dma_sge * dao_dma_sge_dst(struct dao_dma_vchan_state *vchan)
static __rte_always_inline void dao_dma_check_meta_compl(struct dao_dma_vchan_state *vchan, const int mem_order)
static __rte_always_inline uint16_t dao_dma_burst_capacity(struct dao_dma_vchan_state *vchan)
#define DAO_DMA_DOORBELL_THRESHOLD
int dao_dma_lcore_mem2dev_autofree_set(int16_t dma_devid, uint16_t vchan, bool enable)
static __rte_always_inline void dao_dma_ops_release(struct dao_dma_vchan_state *vchan, uint16_t n)
#define DAO_DMA_MAX_INFLIGHT_MDATA
static __rte_always_inline struct rte_dma_op ** dao_dma_ops_get(struct dao_dma_vchan_state *vchan, uint16_t n)
static __rte_always_inline void dao_dma_ops_put(struct dao_dma_vchan_state *vchan, uint16_t n)
int16_t dao_dma_ctrl_mem2dev(void)
void dao_dma_compl_wait_inflight(uint16_t vchan)
static __rte_always_inline void dao_dma_check_compl(struct dao_dma_vchan_state *vchan)
int dao_dma_lcore_mem2dev_set(int16_t dma_devid, uint16_t nb_vchans, uint16_t flush_thr)
static __rte_always_inline bool dao_dma_desc_avail_get(struct dao_dma_vchan_state *vchan, uint32_t nb_src, uint32_t nb_dst)
static __rte_always_inline void dao_dma_enq_x1(struct dao_dma_vchan_state *vchan, rte_iova_t src, uint32_t src_len, rte_iova_t dst, uint32_t dst_len)
int dao_dma_lcore_dev2mem_set_ops(int16_t dma_devid, uint16_t nb_vchans, uint16_t flush_thr, uint16_t nb_ops)
int dao_dma_stats_get(uint16_t lcore_id, struct dao_dma_stats *stats)
static __rte_always_inline void dao_dma_check_meta_compl_ops(struct dao_dma_vchan_state *vchan, const int mem_order)
int dao_dma_flush_submit_ops(void)
#define DAO_DMA_MAX_VCHAN_PER_LCORE
#define DAO_DMA_MAX_META_POINTER
static __rte_always_inline uint16_t dao_dma_src_avail(struct dao_dma_vchan_state *vchan)
int dao_dma_flush_submit(void)
RTE_DECLARE_PER_LCORE(struct dao_dma_vchan_info *, dao_dma_vchan_info)
static __rte_always_inline void dao_dma_enq_dst_x1(struct dao_dma_vchan_state *vchan, rte_iova_t dst, uint32_t dst_len)
static __rte_always_inline void dao_dma_check_meta_compl_v2(struct dao_dma_vchan_state *vchan, const int mem_order)
static __rte_always_inline void dao_dma_op_set_cmpl(struct rte_dma_op *op, uint16_t *ptr, uint16_t val, uint16_t *pend_ptr, uint16_t pend_val)
static __rte_always_inline uint16_t dao_dma_dst_avail(struct dao_dma_vchan_state *vchan)
static __rte_always_inline void dao_dma_update_cmpl_meta_v2(struct dao_dma_vchan_state *vchan, uint32_t *ptr, uint32_t val, uint16_t tail)
static __rte_always_inline bool dao_dma_flush(struct dao_dma_vchan_state *vchan, const uint8_t avail)
static __rte_always_inline struct rte_dma_sge * dao_dma_sge_src(struct dao_dma_vchan_state *vchan)
static __rte_always_inline void dao_dma_update_cmpl_meta(struct dao_dma_vchan_state *vchan, uint16_t *ptr, uint16_t val, uint16_t *pend_ptr, uint16_t pend_val, uint16_t tail)
int dao_dma_flush_submit_v2(void)
static __rte_always_inline bool dao_dma_op_status(struct dao_dma_vchan_state *vchan, uint16_t op_idx)
static __rte_always_inline uint16_t dao_dma_ops_avail(struct dao_dma_vchan_state *vchan)
int dao_dma_lcore_mem2dev_set_ops(int16_t dma_devid, uint16_t nb_vchans, uint16_t flush_thr, uint16_t nb_ops)
int16_t dao_dma_ctrl_dev2mem(void)
static __rte_always_inline uint16_t dao_dma_enq_x4(struct dao_dma_vchan_state *vchan, uint64x2_t *vsrc, uint64x2_t *vdst)
int dao_dma_ctrl_dev_set(int16_t dev2mem_id, int16_t mem2dev_id)
int dao_dma_lcore_dev2mem_set(int16_t dma_devid, uint16_t nb_vchans, uint16_t flush_thr)
#define DAO_DMA_MAX_POINTER
uint16_t * pend_ptr[DAO_DMA_MAX_META_POINTER]
uint16_t * ptr[DAO_DMA_MAX_META_POINTER]
uint16_t pend_val[DAO_DMA_MAX_META_POINTER]
struct dao_dma_vchan_stats dev2mem[DAO_DMA_MAX_VCHAN_PER_LCORE]
struct dao_dma_vchan_stats mem2dev[DAO_DMA_MAX_VCHAN_PER_LCORE]
struct dao_dma_vchan_state mem2dev[DAO_DMA_MAX_VCHAN_PER_LCORE]
struct dao_dma_vchan_state dev2mem[DAO_DMA_MAX_VCHAN_PER_LCORE]
struct rte_dma_sge dst[DAO_DMA_MAX_POINTER]
struct rte_dma_op ** dma_ops
struct rte_dma_sge src[DAO_DMA_MAX_POINTER]
struct dao_dma_cmpl_mdata mdata[DAO_DMA_MAX_INFLIGHT_MDATA]