17d63899aSWei Huang /* SPDX-License-Identifier: BSD-3-Clause 27d63899aSWei Huang * Copyright(c) 2022 Intel Corporation 37d63899aSWei Huang */ 47d63899aSWei Huang 57d63899aSWei Huang #include <errno.h> 67d63899aSWei Huang #include <stdio.h> 77d63899aSWei Huang #include <stdint.h> 87d63899aSWei Huang #include <stdlib.h> 97d63899aSWei Huang #include <inttypes.h> 107d63899aSWei Huang #include <unistd.h> 117d63899aSWei Huang #include <fcntl.h> 127d63899aSWei Huang #include <poll.h> 137d63899aSWei Huang #include <sys/eventfd.h> 147d63899aSWei Huang #include <sys/ioctl.h> 157d63899aSWei Huang 167d63899aSWei Huang #include <rte_eal.h> 177d63899aSWei Huang #include <rte_malloc.h> 187d63899aSWei Huang #include <rte_memcpy.h> 197d63899aSWei Huang #include <rte_io.h> 207d63899aSWei Huang #include <rte_vfio.h> 211f37cb2bSDavid Marchand #include <bus_pci_driver.h> 22925c074eSDavid Marchand #include <bus_ifpga_driver.h> 237d63899aSWei Huang #include <rte_rawdev.h> 247d63899aSWei Huang 257d63899aSWei Huang #include "afu_pmd_core.h" 267d63899aSWei Huang #include "afu_pmd_n3000.h" 277d63899aSWei Huang 287d63899aSWei Huang static int nlb_afu_config(struct afu_rawdev *dev) 297d63899aSWei Huang { 307d63899aSWei Huang struct n3000_afu_priv *priv = NULL; 317d63899aSWei Huang struct rte_pmd_afu_nlb_cfg *cfg = NULL; 327d63899aSWei Huang struct nlb_csr_cfg v; 337d63899aSWei Huang 347d63899aSWei Huang if (!dev) 357d63899aSWei Huang return -EINVAL; 367d63899aSWei Huang 377d63899aSWei Huang if (!dev->priv) 387d63899aSWei Huang return -ENOENT; 397d63899aSWei Huang 407d63899aSWei Huang priv = (struct n3000_afu_priv *)dev->priv; 417d63899aSWei Huang cfg = &priv->nlb_cfg; 427d63899aSWei Huang 437d63899aSWei Huang v.csr = 0; 447d63899aSWei Huang 457d63899aSWei Huang if (cfg->cont) 467d63899aSWei Huang v.cont = 1; 477d63899aSWei Huang 487d63899aSWei Huang if (cfg->cache_policy == NLB_WRPUSH_I) 497d63899aSWei Huang v.wrpush_i = 1; 507d63899aSWei Huang else 517d63899aSWei Huang v.wrthru_en = cfg->cache_policy; 527d63899aSWei Huang 537d63899aSWei Huang if (cfg->cache_hint == NLB_RDLINE_MIXED) 547d63899aSWei Huang v.rdsel = 3; 557d63899aSWei Huang else 567d63899aSWei Huang v.rdsel = cfg->cache_hint; 577d63899aSWei Huang 587d63899aSWei Huang v.mode = cfg->mode; 597d63899aSWei Huang v.chsel = cfg->read_vc; 607d63899aSWei Huang v.wr_chsel = cfg->write_vc; 617d63899aSWei Huang v.wrfence_chsel = cfg->wrfence_vc; 627d63899aSWei Huang v.wrthru_en = cfg->cache_policy; 637d63899aSWei Huang v.multicl_len = cfg->multi_cl - 1; 647d63899aSWei Huang 657d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("cfg: 0x%08x", v.csr); 667d63899aSWei Huang rte_write32(v.csr, priv->nlb_ctx.addr + CSR_CFG); 677d63899aSWei Huang 687d63899aSWei Huang return 0; 697d63899aSWei Huang } 707d63899aSWei Huang 717d63899aSWei Huang static void nlb_afu_report(struct afu_rawdev *dev, uint32_t cl) 727d63899aSWei Huang { 737d63899aSWei Huang struct n3000_afu_priv *priv = NULL; 747d63899aSWei Huang struct rte_pmd_afu_nlb_cfg *cfg = NULL; 757d63899aSWei Huang struct nlb_dsm_status *stat = NULL; 767d63899aSWei Huang uint64_t ticks = 0; 777d63899aSWei Huang double num, rd_bw, wr_bw; 787d63899aSWei Huang 797d63899aSWei Huang if (!dev || !dev->priv) 807d63899aSWei Huang return; 817d63899aSWei Huang 827d63899aSWei Huang priv = (struct n3000_afu_priv *)dev->priv; 837d63899aSWei Huang 847d63899aSWei Huang cfg = &priv->nlb_cfg; 857d63899aSWei Huang stat = priv->nlb_ctx.status_ptr; 867d63899aSWei Huang 877d63899aSWei Huang if (cfg->cont) 887d63899aSWei Huang ticks = stat->num_clocks - stat->start_overhead; 897d63899aSWei Huang else 907d63899aSWei Huang ticks = stat->num_clocks - 917d63899aSWei Huang (stat->start_overhead + stat->end_overhead); 927d63899aSWei Huang 937d63899aSWei Huang if (cfg->freq_mhz == 0) 947d63899aSWei Huang cfg->freq_mhz = 200; 957d63899aSWei Huang 967d63899aSWei Huang num = (double)stat->num_reads; 977d63899aSWei Huang rd_bw = (num * CLS_TO_SIZE(1) * MHZ(cfg->freq_mhz)) / ticks; 987d63899aSWei Huang num = (double)stat->num_writes; 997d63899aSWei Huang wr_bw = (num * CLS_TO_SIZE(1) * MHZ(cfg->freq_mhz)) / ticks; 1007d63899aSWei Huang 1017d63899aSWei Huang printf("Cachelines Read_Count Write_Count Clocks@%uMHz " 1027d63899aSWei Huang "Rd_Bandwidth Wr_Bandwidth\n", cfg->freq_mhz); 1037d63899aSWei Huang printf("%10u %10u %11u %12"PRIu64" %7.3f GB/s %7.3f GB/s\n", 1047d63899aSWei Huang cl, stat->num_reads, stat->num_writes, ticks, 1057d63899aSWei Huang rd_bw / 1e9, wr_bw / 1e9); 1067d63899aSWei Huang } 1077d63899aSWei Huang 1087d63899aSWei Huang static int nlb_afu_test(struct afu_rawdev *dev) 1097d63899aSWei Huang { 1107d63899aSWei Huang struct n3000_afu_priv *priv = NULL; 1117d63899aSWei Huang struct nlb_afu_ctx *ctx = NULL; 1127d63899aSWei Huang struct rte_pmd_afu_nlb_cfg *cfg = NULL; 1137d63899aSWei Huang struct nlb_csr_ctl ctl; 1147d63899aSWei Huang uint32_t *ptr = NULL; 1157d63899aSWei Huang uint32_t i, j, cl, val = 0; 1167d63899aSWei Huang uint64_t sval = 0; 1177d63899aSWei Huang int ret = 0; 1187d63899aSWei Huang 1197d63899aSWei Huang if (!dev) 1207d63899aSWei Huang return -EINVAL; 1217d63899aSWei Huang 1227d63899aSWei Huang if (!dev->priv) 1237d63899aSWei Huang return -ENOENT; 1247d63899aSWei Huang 1257d63899aSWei Huang priv = (struct n3000_afu_priv *)dev->priv; 1267d63899aSWei Huang ctx = &priv->nlb_ctx; 1277d63899aSWei Huang cfg = &priv->nlb_cfg; 1287d63899aSWei Huang 1297d63899aSWei Huang /* initialize registers */ 1307d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("dsm_addr: 0x%"PRIx64, ctx->dsm_iova); 1317d63899aSWei Huang rte_write64(ctx->dsm_iova, ctx->addr + CSR_AFU_DSM_BASEL); 1327d63899aSWei Huang 1337d63899aSWei Huang ctl.csr = 0; 1347d63899aSWei Huang rte_write32(ctl.csr, ctx->addr + CSR_CTL); 1357d63899aSWei Huang ctl.reset = 1; 1367d63899aSWei Huang rte_write32(ctl.csr, ctx->addr + CSR_CTL); 1377d63899aSWei Huang 1387d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("src_addr: 0x%"PRIx64, ctx->src_iova); 1397d63899aSWei Huang rte_write64(SIZE_TO_CLS(ctx->src_iova), ctx->addr + CSR_SRC_ADDR); 1407d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("dst_addr: 0x%"PRIx64, ctx->dest_iova); 1417d63899aSWei Huang rte_write64(SIZE_TO_CLS(ctx->dest_iova), ctx->addr + CSR_DST_ADDR); 1427d63899aSWei Huang 1437d63899aSWei Huang ret = nlb_afu_config(dev); 1447d63899aSWei Huang if (ret) 1457d63899aSWei Huang return ret; 1467d63899aSWei Huang 1477d63899aSWei Huang /* initialize src data */ 1487d63899aSWei Huang ptr = (uint32_t *)ctx->src_ptr; 1497d63899aSWei Huang j = CLS_TO_SIZE(cfg->end) >> 2; 1507d63899aSWei Huang for (i = 0; i < j; i++) 1517d63899aSWei Huang *ptr++ = i; 1527d63899aSWei Huang 1537d63899aSWei Huang /* start test */ 1547d63899aSWei Huang for (cl = cfg->begin; cl <= cfg->end; cl += cfg->multi_cl) { 1557d63899aSWei Huang memset(ctx->dest_ptr, 0, CLS_TO_SIZE(cl)); 1567d63899aSWei Huang memset(ctx->dsm_ptr, 0, DSM_SIZE); 1577d63899aSWei Huang 1587d63899aSWei Huang ctl.csr = 0; 1597d63899aSWei Huang rte_write32(ctl.csr, ctx->addr + CSR_CTL); 1607d63899aSWei Huang ctl.reset = 1; 1617d63899aSWei Huang rte_write32(ctl.csr, ctx->addr + CSR_CTL); 1627d63899aSWei Huang 1637d63899aSWei Huang rte_write32(cl, ctx->addr + CSR_NUM_LINES); 1647d63899aSWei Huang 1657d63899aSWei Huang rte_delay_us(10); 1667d63899aSWei Huang 1677d63899aSWei Huang ctl.start = 1; 1687d63899aSWei Huang rte_write32(ctl.csr, ctx->addr + CSR_CTL); 1697d63899aSWei Huang 1707d63899aSWei Huang if (cfg->cont) { 1717d63899aSWei Huang rte_delay_ms(cfg->timeout * 1000); 1727d63899aSWei Huang ctl.force_completion = 1; 1737d63899aSWei Huang rte_write32(ctl.csr, ctx->addr + CSR_CTL); 1747d63899aSWei Huang ret = dsm_poll_timeout(&ctx->status_ptr->test_complete, 1757d63899aSWei Huang val, (val & 0x1) == 1, DSM_POLL_INTERVAL, 1767d63899aSWei Huang DSM_TIMEOUT); 1777d63899aSWei Huang if (ret) { 1787d63899aSWei Huang printf("DSM poll timeout\n"); 1797d63899aSWei Huang goto end; 1807d63899aSWei Huang } 1817d63899aSWei Huang } else { 1827d63899aSWei Huang ret = dsm_poll_timeout(&ctx->status_ptr->test_complete, 1837d63899aSWei Huang val, (val & 0x1) == 1, DSM_POLL_INTERVAL, 1847d63899aSWei Huang DSM_TIMEOUT); 1857d63899aSWei Huang if (ret) { 1867d63899aSWei Huang printf("DSM poll timeout\n"); 1877d63899aSWei Huang goto end; 1887d63899aSWei Huang } 1897d63899aSWei Huang ctl.force_completion = 1; 1907d63899aSWei Huang rte_write32(ctl.csr, ctx->addr + CSR_CTL); 1917d63899aSWei Huang } 1927d63899aSWei Huang 1937d63899aSWei Huang nlb_afu_report(dev, cl); 1947d63899aSWei Huang 1957d63899aSWei Huang i = 0; 1967d63899aSWei Huang while (i++ < 100) { 1977d63899aSWei Huang sval = rte_read64(ctx->addr + CSR_STATUS1); 1987d63899aSWei Huang if (sval == 0) 1997d63899aSWei Huang break; 2007d63899aSWei Huang rte_delay_us(1000); 2017d63899aSWei Huang } 2027d63899aSWei Huang 2037d63899aSWei Huang ptr = (uint32_t *)ctx->dest_ptr; 2047d63899aSWei Huang j = CLS_TO_SIZE(cl) >> 2; 2057d63899aSWei Huang for (i = 0; i < j; i++) { 2067d63899aSWei Huang if (*ptr++ != i) { 2077d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Data mismatch @ %u", i); 2087d63899aSWei Huang break; 2097d63899aSWei Huang } 2107d63899aSWei Huang } 2117d63899aSWei Huang } 2127d63899aSWei Huang 2137d63899aSWei Huang end: 2147d63899aSWei Huang return ret; 2157d63899aSWei Huang } 2167d63899aSWei Huang 2177d63899aSWei Huang static void dma_afu_buf_free(struct dma_afu_ctx *ctx) 2187d63899aSWei Huang { 2197d63899aSWei Huang int i = 0; 2207d63899aSWei Huang 2217d63899aSWei Huang if (!ctx) 2227d63899aSWei Huang return; 2237d63899aSWei Huang 2247d63899aSWei Huang for (i = 0; i < NUM_DMA_BUF; i++) { 2257d63899aSWei Huang rte_free(ctx->dma_buf[i]); 2267d63899aSWei Huang ctx->dma_buf[i] = NULL; 2277d63899aSWei Huang } 2287d63899aSWei Huang 2297d63899aSWei Huang rte_free(ctx->data_buf); 2307d63899aSWei Huang ctx->data_buf = NULL; 2317d63899aSWei Huang 2327d63899aSWei Huang rte_free(ctx->ref_buf); 2337d63899aSWei Huang ctx->ref_buf = NULL; 2347d63899aSWei Huang } 2357d63899aSWei Huang 2367d63899aSWei Huang static int dma_afu_buf_alloc(struct dma_afu_ctx *ctx, 2377d63899aSWei Huang struct rte_pmd_afu_dma_cfg *cfg) 2387d63899aSWei Huang { 2397d63899aSWei Huang size_t page_sz = sysconf(_SC_PAGE_SIZE); 2407d63899aSWei Huang int i, ret = 0; 2417d63899aSWei Huang 2427d63899aSWei Huang if (!ctx || !cfg) 2437d63899aSWei Huang return -EINVAL; 2447d63899aSWei Huang 2457d63899aSWei Huang for (i = 0; i < NUM_DMA_BUF; i++) { 2467d63899aSWei Huang ctx->dma_buf[i] = (uint64_t *)rte_zmalloc(NULL, cfg->size, 2477d63899aSWei Huang TEST_MEM_ALIGN); 2487d63899aSWei Huang if (!ctx->dma_buf[i]) { 2497d63899aSWei Huang ret = -ENOMEM; 2507d63899aSWei Huang goto free_dma_buf; 2517d63899aSWei Huang } 2527d63899aSWei Huang ctx->dma_iova[i] = rte_malloc_virt2iova(ctx->dma_buf[i]); 2537d63899aSWei Huang if (ctx->dma_iova[i] == RTE_BAD_IOVA) { 2547d63899aSWei Huang ret = -ENOMEM; 2557d63899aSWei Huang goto free_dma_buf; 2567d63899aSWei Huang } 2577d63899aSWei Huang } 2587d63899aSWei Huang 2597d63899aSWei Huang ctx->data_buf = rte_malloc(NULL, cfg->length, page_sz); 2607d63899aSWei Huang if (!ctx->data_buf) { 2617d63899aSWei Huang ret = -ENOMEM; 2627d63899aSWei Huang goto free_dma_buf; 2637d63899aSWei Huang } 2647d63899aSWei Huang 2657d63899aSWei Huang ctx->ref_buf = rte_malloc(NULL, cfg->length, page_sz); 2667d63899aSWei Huang if (!ctx->ref_buf) { 2677d63899aSWei Huang ret = -ENOMEM; 2687d63899aSWei Huang goto free_data_buf; 2697d63899aSWei Huang } 2707d63899aSWei Huang 2717d63899aSWei Huang return 0; 2727d63899aSWei Huang 2737d63899aSWei Huang free_data_buf: 2747d63899aSWei Huang rte_free(ctx->data_buf); 2757d63899aSWei Huang ctx->data_buf = NULL; 2767d63899aSWei Huang free_dma_buf: 2777d63899aSWei Huang for (i = 0; i < NUM_DMA_BUF; i++) { 2787d63899aSWei Huang rte_free(ctx->dma_buf[i]); 2797d63899aSWei Huang ctx->dma_buf[i] = NULL; 2807d63899aSWei Huang } 2817d63899aSWei Huang return ret; 2827d63899aSWei Huang } 2837d63899aSWei Huang 2847d63899aSWei Huang static void dma_afu_buf_init(struct dma_afu_ctx *ctx, size_t size) 2857d63899aSWei Huang { 2867d63899aSWei Huang int *ptr = NULL; 2877d63899aSWei Huang size_t i = 0; 2887d63899aSWei Huang size_t dword_size = 0; 2897d63899aSWei Huang 2907d63899aSWei Huang if (!ctx || !size) 2917d63899aSWei Huang return; 2927d63899aSWei Huang 2937d63899aSWei Huang ptr = (int *)ctx->ref_buf; 2947d63899aSWei Huang 2957d63899aSWei Huang if (ctx->pattern) { 2967d63899aSWei Huang memset(ptr, ctx->pattern, size); 2977d63899aSWei Huang } else { 2987d63899aSWei Huang srand(99); 2997d63899aSWei Huang dword_size = size >> 2; 3007d63899aSWei Huang for (i = 0; i < dword_size; i++) 3017d63899aSWei Huang *ptr++ = rand(); 3027d63899aSWei Huang } 3037d63899aSWei Huang rte_memcpy(ctx->data_buf, ctx->ref_buf, size); 3047d63899aSWei Huang } 3057d63899aSWei Huang 3067d63899aSWei Huang static int dma_afu_buf_verify(struct dma_afu_ctx *ctx, size_t size) 3077d63899aSWei Huang { 3087d63899aSWei Huang uint8_t *src = NULL; 3097d63899aSWei Huang uint8_t *dst = NULL; 3107d63899aSWei Huang size_t i = 0; 3117d63899aSWei Huang int n = 0; 3127d63899aSWei Huang 3137d63899aSWei Huang if (!ctx || !size) 3147d63899aSWei Huang return -EINVAL; 3157d63899aSWei Huang 3167d63899aSWei Huang src = (uint8_t *)ctx->ref_buf; 3177d63899aSWei Huang dst = (uint8_t *)ctx->data_buf; 3187d63899aSWei Huang 3197d63899aSWei Huang if (memcmp(src, dst, size)) { 3207d63899aSWei Huang printf("Transfer is corrupted\n"); 3217d63899aSWei Huang if (ctx->verbose) { 3227d63899aSWei Huang for (i = 0; i < size; i++) { 3237d63899aSWei Huang if (*src != *dst) { 3247d63899aSWei Huang if (++n >= ERR_CHECK_LIMIT) 3257d63899aSWei Huang break; 3267d63899aSWei Huang printf("Mismatch at 0x%zx, " 3277d63899aSWei Huang "Expected %02x Actual %02x\n", 3287d63899aSWei Huang i, *src, *dst); 3297d63899aSWei Huang } 3307d63899aSWei Huang src++; 3317d63899aSWei Huang dst++; 3327d63899aSWei Huang } 3337d63899aSWei Huang if (n < ERR_CHECK_LIMIT) { 3347d63899aSWei Huang printf("Found %d error bytes\n", n); 3357d63899aSWei Huang } else { 3367d63899aSWei Huang printf("......\n"); 3377d63899aSWei Huang printf("Found more than %d error bytes\n", n); 3387d63899aSWei Huang } 3397d63899aSWei Huang } 3407d63899aSWei Huang return -1; 3417d63899aSWei Huang } 3427d63899aSWei Huang 3437d63899aSWei Huang printf("Transfer is verified\n"); 3447d63899aSWei Huang return 0; 3457d63899aSWei Huang } 3467d63899aSWei Huang 3477d63899aSWei Huang static void blk_write64(uint64_t *dev_addr, uint64_t *host_addr, uint64_t bytes) 3487d63899aSWei Huang { 3497d63899aSWei Huang uint64_t qwords = bytes / sizeof(uint64_t); 3507d63899aSWei Huang 3517d63899aSWei Huang if (!IS_ALIGNED_QWORD((uint64_t)dev_addr) || 3527d63899aSWei Huang !IS_ALIGNED_QWORD((uint64_t)bytes)) 3537d63899aSWei Huang return; 3547d63899aSWei Huang 3557d63899aSWei Huang for (; qwords > 0; qwords--, host_addr++, dev_addr++) 3567d63899aSWei Huang rte_write64(*host_addr, dev_addr); 3577d63899aSWei Huang } 3587d63899aSWei Huang 3597d63899aSWei Huang static void blk_read64(uint64_t *dev_addr, uint64_t *host_addr, uint64_t bytes) 3607d63899aSWei Huang { 3617d63899aSWei Huang uint64_t qwords = bytes / sizeof(uint64_t); 3627d63899aSWei Huang 3637d63899aSWei Huang if (!IS_ALIGNED_QWORD((uint64_t)dev_addr) || 3647d63899aSWei Huang !IS_ALIGNED_QWORD((uint64_t)bytes)) 3657d63899aSWei Huang return; 3667d63899aSWei Huang 3677d63899aSWei Huang for (; qwords > 0; qwords--, host_addr++, dev_addr++) 3687d63899aSWei Huang *host_addr = rte_read64(dev_addr); 3697d63899aSWei Huang } 3707d63899aSWei Huang 3717d63899aSWei Huang static void switch_ase_page(struct dma_afu_ctx *ctx, uint64_t addr) 3727d63899aSWei Huang { 3737d63899aSWei Huang uint64_t requested_page = addr & ~DMA_ASE_WINDOW_MASK; 3747d63899aSWei Huang 3757d63899aSWei Huang if (!ctx) 3767d63899aSWei Huang return; 3777d63899aSWei Huang 3787d63899aSWei Huang if (requested_page != ctx->cur_ase_page) { 3797d63899aSWei Huang rte_write64(requested_page, ctx->ase_ctrl_addr); 3807d63899aSWei Huang ctx->cur_ase_page = requested_page; 3817d63899aSWei Huang } 3827d63899aSWei Huang } 3837d63899aSWei Huang 3847d63899aSWei Huang static int ase_write_unaligned(struct dma_afu_ctx *ctx, uint64_t dev_addr, 3857d63899aSWei Huang uint64_t host_addr, uint32_t count) 3867d63899aSWei Huang { 3877d63899aSWei Huang uint64_t dev_aligned_addr = 0; 3887d63899aSWei Huang uint64_t shift = 0; 3897d63899aSWei Huang uint64_t val = 0; 3907d63899aSWei Huang uintptr_t addr = (uintptr_t)host_addr; /* transfer to pointer size */ 3917d63899aSWei Huang 3927d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" --> 0x%"PRIx64" (0x%x)", host_addr, 3937d63899aSWei Huang dev_addr, count); 3947d63899aSWei Huang 3957d63899aSWei Huang if (!ctx || (count >= QWORD_BYTES)) 3967d63899aSWei Huang return -EINVAL; 3977d63899aSWei Huang 3987d63899aSWei Huang if (!count) 3997d63899aSWei Huang return 0; 4007d63899aSWei Huang 4017d63899aSWei Huang switch_ase_page(ctx, dev_addr); 4027d63899aSWei Huang 4037d63899aSWei Huang shift = dev_addr % QWORD_BYTES; 4047d63899aSWei Huang dev_aligned_addr = (dev_addr - shift) & DMA_ASE_WINDOW_MASK; 4057d63899aSWei Huang val = rte_read64(ctx->ase_data_addr + dev_aligned_addr); 4067d63899aSWei Huang rte_memcpy(((char *)(&val)) + shift, (void *)addr, count); 4077d63899aSWei Huang 4087d63899aSWei Huang /* write back to device */ 4097d63899aSWei Huang rte_write64(val, ctx->ase_data_addr + dev_aligned_addr); 4107d63899aSWei Huang 4117d63899aSWei Huang return 0; 4127d63899aSWei Huang } 4137d63899aSWei Huang 4147d63899aSWei Huang static int ase_write(struct dma_afu_ctx *ctx, uint64_t *dst_ptr, 4157d63899aSWei Huang uint64_t *src_ptr, uint64_t *count) 4167d63899aSWei Huang { 4177d63899aSWei Huang uint64_t src = *src_ptr; 4187d63899aSWei Huang uint64_t dst = *dst_ptr; 4197d63899aSWei Huang uint64_t align_bytes = *count; 4207d63899aSWei Huang uint64_t offset = 0; 4217d63899aSWei Huang uint64_t left_in_page = DMA_ASE_WINDOW; 4227d63899aSWei Huang uint64_t size_to_copy = 0; 4237d63899aSWei Huang 4247d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" --> 0x%"PRIx64" (0x%"PRIx64")", src, dst, 4257d63899aSWei Huang align_bytes); 4267d63899aSWei Huang 4277d63899aSWei Huang if (!ctx || !IS_ALIGNED_DWORD(dst)) 4287d63899aSWei Huang return -EINVAL; 4297d63899aSWei Huang 4307d63899aSWei Huang if (align_bytes < DWORD_BYTES) 4317d63899aSWei Huang return 0; 4327d63899aSWei Huang 4337d63899aSWei Huang if (!IS_ALIGNED_QWORD(dst)) { 4347d63899aSWei Huang /* Write out a single DWORD to get QWORD aligned */ 4357d63899aSWei Huang switch_ase_page(ctx, dst); 4367d63899aSWei Huang offset = dst & DMA_ASE_WINDOW_MASK; 4377d63899aSWei Huang 4387d63899aSWei Huang rte_write32(*(uint32_t *)(uintptr_t)src, 4397d63899aSWei Huang ctx->ase_data_addr + offset); 4407d63899aSWei Huang src += DWORD_BYTES; 4417d63899aSWei Huang dst += DWORD_BYTES; 4427d63899aSWei Huang align_bytes -= DWORD_BYTES; 4437d63899aSWei Huang } 4447d63899aSWei Huang 4457d63899aSWei Huang if (!align_bytes) 4467d63899aSWei Huang return 0; 4477d63899aSWei Huang 4487d63899aSWei Huang /* Write out blocks of 64-bit values */ 4497d63899aSWei Huang while (align_bytes >= QWORD_BYTES) { 4507d63899aSWei Huang left_in_page -= dst & DMA_ASE_WINDOW_MASK; 4517d63899aSWei Huang size_to_copy = 4527d63899aSWei Huang MIN(left_in_page, (align_bytes & ~(QWORD_BYTES - 1))); 4537d63899aSWei Huang if (size_to_copy < QWORD_BYTES) 4547d63899aSWei Huang break; 4557d63899aSWei Huang switch_ase_page(ctx, dst); 4567d63899aSWei Huang offset = dst & DMA_ASE_WINDOW_MASK; 4577d63899aSWei Huang blk_write64((uint64_t *)(ctx->ase_data_addr + offset), 4587d63899aSWei Huang (uint64_t *)(uintptr_t)src, size_to_copy); 4597d63899aSWei Huang src += size_to_copy; 4607d63899aSWei Huang dst += size_to_copy; 4617d63899aSWei Huang align_bytes -= size_to_copy; 4627d63899aSWei Huang } 4637d63899aSWei Huang 4647d63899aSWei Huang if (align_bytes >= DWORD_BYTES) { 4657d63899aSWei Huang /* Write out remaining DWORD */ 4667d63899aSWei Huang switch_ase_page(ctx, dst); 4677d63899aSWei Huang offset = dst & DMA_ASE_WINDOW_MASK; 4687d63899aSWei Huang rte_write32(*(uint32_t *)(uintptr_t)src, 4697d63899aSWei Huang ctx->ase_data_addr + offset); 4707d63899aSWei Huang src += DWORD_BYTES; 4717d63899aSWei Huang dst += DWORD_BYTES; 4727d63899aSWei Huang align_bytes -= DWORD_BYTES; 4737d63899aSWei Huang } 4747d63899aSWei Huang 4757d63899aSWei Huang *src_ptr = src; 4767d63899aSWei Huang *dst_ptr = dst; 4777d63899aSWei Huang *count = align_bytes; 4787d63899aSWei Huang 4797d63899aSWei Huang return 0; 4807d63899aSWei Huang } 4817d63899aSWei Huang 4827d63899aSWei Huang static int ase_host_to_fpga(struct dma_afu_ctx *ctx, uint64_t *dst_ptr, 4837d63899aSWei Huang uint64_t *src_ptr, uint64_t count) 4847d63899aSWei Huang { 4857d63899aSWei Huang uint64_t dst = *dst_ptr; 4867d63899aSWei Huang uint64_t src = *src_ptr; 4877d63899aSWei Huang uint64_t count_left = count; 4887d63899aSWei Huang uint64_t unaligned_size = 0; 4897d63899aSWei Huang int ret = 0; 4907d63899aSWei Huang 4917d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" --> 0x%"PRIx64" (0x%"PRIx64")", src, dst, 4927d63899aSWei Huang count); 4937d63899aSWei Huang 4947d63899aSWei Huang /* aligns address to 8 byte using dst masking method */ 4957d63899aSWei Huang if (!IS_ALIGNED_DWORD(dst) && !IS_ALIGNED_QWORD(dst)) { 4967d63899aSWei Huang unaligned_size = QWORD_BYTES - (dst % QWORD_BYTES); 4977d63899aSWei Huang if (unaligned_size > count_left) 4987d63899aSWei Huang unaligned_size = count_left; 4997d63899aSWei Huang ret = ase_write_unaligned(ctx, dst, src, unaligned_size); 5007d63899aSWei Huang if (ret) 5017d63899aSWei Huang return ret; 5027d63899aSWei Huang count_left -= unaligned_size; 5037d63899aSWei Huang src += unaligned_size; 5047d63899aSWei Huang dst += unaligned_size; 5057d63899aSWei Huang } 5067d63899aSWei Huang 5077d63899aSWei Huang /* Handles 8/4 byte MMIO transfer */ 5087d63899aSWei Huang ret = ase_write(ctx, &dst, &src, &count_left); 5097d63899aSWei Huang if (ret) 5107d63899aSWei Huang return ret; 5117d63899aSWei Huang 5127d63899aSWei Huang /* Left over unaligned bytes transferred using dst masking method */ 5137d63899aSWei Huang unaligned_size = QWORD_BYTES - (dst % QWORD_BYTES); 5147d63899aSWei Huang if (unaligned_size > count_left) 5157d63899aSWei Huang unaligned_size = count_left; 5167d63899aSWei Huang 5177d63899aSWei Huang ret = ase_write_unaligned(ctx, dst, src, unaligned_size); 5187d63899aSWei Huang if (ret) 5197d63899aSWei Huang return ret; 5207d63899aSWei Huang 5217d63899aSWei Huang count_left -= unaligned_size; 5227d63899aSWei Huang *dst_ptr = dst + unaligned_size; 5237d63899aSWei Huang *src_ptr = src + unaligned_size; 5247d63899aSWei Huang 5257d63899aSWei Huang return 0; 5267d63899aSWei Huang } 5277d63899aSWei Huang 5287d63899aSWei Huang static int ase_read_unaligned(struct dma_afu_ctx *ctx, uint64_t dev_addr, 5297d63899aSWei Huang uint64_t host_addr, uint32_t count) 5307d63899aSWei Huang { 5317d63899aSWei Huang uint64_t dev_aligned_addr = 0; 5327d63899aSWei Huang uint64_t shift = 0; 5337d63899aSWei Huang uint64_t val = 0; 5347d63899aSWei Huang uintptr_t addr = (uintptr_t)host_addr; /* transfer to pointer size */ 5357d63899aSWei Huang 5367d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" <-- 0x%"PRIx64" (0x%x)", host_addr, 5377d63899aSWei Huang dev_addr, count); 5387d63899aSWei Huang 5397d63899aSWei Huang if (!ctx || (count >= QWORD_BYTES)) 5407d63899aSWei Huang return -EINVAL; 5417d63899aSWei Huang 5427d63899aSWei Huang if (!count) 5437d63899aSWei Huang return 0; 5447d63899aSWei Huang 5457d63899aSWei Huang switch_ase_page(ctx, dev_addr); 5467d63899aSWei Huang 5477d63899aSWei Huang shift = dev_addr % QWORD_BYTES; 5487d63899aSWei Huang dev_aligned_addr = (dev_addr - shift) & DMA_ASE_WINDOW_MASK; 5497d63899aSWei Huang val = rte_read64(ctx->ase_data_addr + dev_aligned_addr); 5507d63899aSWei Huang rte_memcpy((void *)addr, ((char *)(&val)) + shift, count); 5517d63899aSWei Huang 5527d63899aSWei Huang return 0; 5537d63899aSWei Huang } 5547d63899aSWei Huang 5557d63899aSWei Huang static int ase_read(struct dma_afu_ctx *ctx, uint64_t *src_ptr, 5567d63899aSWei Huang uint64_t *dst_ptr, uint64_t *count) 5577d63899aSWei Huang { 5587d63899aSWei Huang uint64_t src = *src_ptr; 5597d63899aSWei Huang uint64_t dst = *dst_ptr; 5607d63899aSWei Huang uint64_t align_bytes = *count; 5617d63899aSWei Huang uint64_t offset = 0; 5627d63899aSWei Huang uint64_t left_in_page = DMA_ASE_WINDOW; 5637d63899aSWei Huang uint64_t size_to_copy = 0; 5647d63899aSWei Huang 5657d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" <-- 0x%"PRIx64" (0x%"PRIx64")", dst, src, 5667d63899aSWei Huang align_bytes); 5677d63899aSWei Huang 5687d63899aSWei Huang if (!ctx || !IS_ALIGNED_DWORD(src)) 5697d63899aSWei Huang return -EINVAL; 5707d63899aSWei Huang 5717d63899aSWei Huang if (align_bytes < DWORD_BYTES) 5727d63899aSWei Huang return 0; 5737d63899aSWei Huang 5747d63899aSWei Huang if (!IS_ALIGNED_QWORD(src)) { 5757d63899aSWei Huang /* Read a single DWORD to get QWORD aligned */ 5767d63899aSWei Huang switch_ase_page(ctx, src); 5777d63899aSWei Huang offset = src & DMA_ASE_WINDOW_MASK; 5787d63899aSWei Huang *(uint32_t *)(uintptr_t)dst = 5797d63899aSWei Huang rte_read32(ctx->ase_data_addr + offset); 5807d63899aSWei Huang src += DWORD_BYTES; 5817d63899aSWei Huang dst += DWORD_BYTES; 5827d63899aSWei Huang align_bytes -= DWORD_BYTES; 5837d63899aSWei Huang } 5847d63899aSWei Huang 5857d63899aSWei Huang if (!align_bytes) 5867d63899aSWei Huang return 0; 5877d63899aSWei Huang 5887d63899aSWei Huang /* Read blocks of 64-bit values */ 5897d63899aSWei Huang while (align_bytes >= QWORD_BYTES) { 5907d63899aSWei Huang left_in_page -= src & DMA_ASE_WINDOW_MASK; 5917d63899aSWei Huang size_to_copy = 5927d63899aSWei Huang MIN(left_in_page, (align_bytes & ~(QWORD_BYTES - 1))); 5937d63899aSWei Huang if (size_to_copy < QWORD_BYTES) 5947d63899aSWei Huang break; 5957d63899aSWei Huang switch_ase_page(ctx, src); 5967d63899aSWei Huang offset = src & DMA_ASE_WINDOW_MASK; 5977d63899aSWei Huang blk_read64((uint64_t *)(ctx->ase_data_addr + offset), 5987d63899aSWei Huang (uint64_t *)(uintptr_t)dst, size_to_copy); 5997d63899aSWei Huang src += size_to_copy; 6007d63899aSWei Huang dst += size_to_copy; 6017d63899aSWei Huang align_bytes -= size_to_copy; 6027d63899aSWei Huang } 6037d63899aSWei Huang 6047d63899aSWei Huang if (align_bytes >= DWORD_BYTES) { 6057d63899aSWei Huang /* Read remaining DWORD */ 6067d63899aSWei Huang switch_ase_page(ctx, src); 6077d63899aSWei Huang offset = src & DMA_ASE_WINDOW_MASK; 6087d63899aSWei Huang *(uint32_t *)(uintptr_t)dst = 6097d63899aSWei Huang rte_read32(ctx->ase_data_addr + offset); 6107d63899aSWei Huang src += DWORD_BYTES; 6117d63899aSWei Huang dst += DWORD_BYTES; 6127d63899aSWei Huang align_bytes -= DWORD_BYTES; 6137d63899aSWei Huang } 6147d63899aSWei Huang 6157d63899aSWei Huang *src_ptr = src; 6167d63899aSWei Huang *dst_ptr = dst; 6177d63899aSWei Huang *count = align_bytes; 6187d63899aSWei Huang 6197d63899aSWei Huang return 0; 6207d63899aSWei Huang } 6217d63899aSWei Huang 6227d63899aSWei Huang static int ase_fpga_to_host(struct dma_afu_ctx *ctx, uint64_t *src_ptr, 6237d63899aSWei Huang uint64_t *dst_ptr, uint64_t count) 6247d63899aSWei Huang { 6257d63899aSWei Huang uint64_t src = *src_ptr; 6267d63899aSWei Huang uint64_t dst = *dst_ptr; 6277d63899aSWei Huang uint64_t count_left = count; 6287d63899aSWei Huang uint64_t unaligned_size = 0; 6297d63899aSWei Huang int ret = 0; 6307d63899aSWei Huang 6317d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" --> 0x%"PRIx64" (0x%"PRIx64")", src, dst, 6327d63899aSWei Huang count); 6337d63899aSWei Huang 6347d63899aSWei Huang /* Aligns address to 8 byte using src masking method */ 6357d63899aSWei Huang if (!IS_ALIGNED_DWORD(src) && !IS_ALIGNED_QWORD(src)) { 6367d63899aSWei Huang unaligned_size = QWORD_BYTES - (src % QWORD_BYTES); 6377d63899aSWei Huang if (unaligned_size > count_left) 6387d63899aSWei Huang unaligned_size = count_left; 6397d63899aSWei Huang ret = ase_read_unaligned(ctx, src, dst, unaligned_size); 6407d63899aSWei Huang if (ret) 6417d63899aSWei Huang return ret; 6427d63899aSWei Huang count_left -= unaligned_size; 6437d63899aSWei Huang dst += unaligned_size; 6447d63899aSWei Huang src += unaligned_size; 6457d63899aSWei Huang } 6467d63899aSWei Huang 6477d63899aSWei Huang /* Handles 8/4 byte MMIO transfer */ 6487d63899aSWei Huang ret = ase_read(ctx, &src, &dst, &count_left); 6497d63899aSWei Huang if (ret) 6507d63899aSWei Huang return ret; 6517d63899aSWei Huang 6527d63899aSWei Huang /* Left over unaligned bytes transferred using src masking method */ 6537d63899aSWei Huang unaligned_size = QWORD_BYTES - (src % QWORD_BYTES); 6547d63899aSWei Huang if (unaligned_size > count_left) 6557d63899aSWei Huang unaligned_size = count_left; 6567d63899aSWei Huang 6577d63899aSWei Huang ret = ase_read_unaligned(ctx, src, dst, unaligned_size); 6587d63899aSWei Huang if (ret) 6597d63899aSWei Huang return ret; 6607d63899aSWei Huang 6617d63899aSWei Huang count_left -= unaligned_size; 6627d63899aSWei Huang *dst_ptr = dst + unaligned_size; 6637d63899aSWei Huang *src_ptr = src + unaligned_size; 6647d63899aSWei Huang 6657d63899aSWei Huang return 0; 6667d63899aSWei Huang } 6677d63899aSWei Huang 6687d63899aSWei Huang static void clear_interrupt(struct dma_afu_ctx *ctx) 6697d63899aSWei Huang { 6707d63899aSWei Huang /* clear interrupt by writing 1 to IRQ bit in status register */ 6717d63899aSWei Huang msgdma_status status; 6727d63899aSWei Huang 6737d63899aSWei Huang if (!ctx) 6747d63899aSWei Huang return; 6757d63899aSWei Huang 6767d63899aSWei Huang status.csr = 0; 6777d63899aSWei Huang status.irq = 1; 6787d63899aSWei Huang rte_write32(status.csr, CSR_STATUS(ctx->csr_addr)); 6797d63899aSWei Huang } 6807d63899aSWei Huang 6817d63899aSWei Huang static int poll_interrupt(struct dma_afu_ctx *ctx) 6827d63899aSWei Huang { 6837d63899aSWei Huang struct pollfd pfd = {0}; 6847d63899aSWei Huang uint64_t count = 0; 6857d63899aSWei Huang ssize_t bytes_read = 0; 6867d63899aSWei Huang int poll_ret = 0; 6877d63899aSWei Huang int ret = 0; 6887d63899aSWei Huang 6897d63899aSWei Huang if (!ctx || (ctx->event_fd < 0)) 6907d63899aSWei Huang return -EINVAL; 6917d63899aSWei Huang 6927d63899aSWei Huang pfd.fd = ctx->event_fd; 6937d63899aSWei Huang pfd.events = POLLIN; 6947d63899aSWei Huang poll_ret = poll(&pfd, 1, DMA_TIMEOUT_MSEC); 6957d63899aSWei Huang if (poll_ret < 0) { 6967d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Error %s", strerror(errno)); 6977d63899aSWei Huang ret = -EFAULT; 6987d63899aSWei Huang goto out; 6997d63899aSWei Huang } else if (poll_ret == 0) { 7007d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Timeout"); 7017d63899aSWei Huang ret = -ETIMEDOUT; 7027d63899aSWei Huang } else { 7037d63899aSWei Huang bytes_read = read(pfd.fd, &count, sizeof(count)); 7047d63899aSWei Huang if (bytes_read > 0) { 7057d63899aSWei Huang if (ctx->verbose) 7067d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("Successful, ret %d, cnt %"PRIu64, 7077d63899aSWei Huang poll_ret, count); 7087d63899aSWei Huang ret = 0; 7097d63899aSWei Huang } else { 7107d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Failed %s", bytes_read > 0 ? 7117d63899aSWei Huang strerror(errno) : "zero bytes read"); 7127d63899aSWei Huang ret = -EIO; 7137d63899aSWei Huang } 7147d63899aSWei Huang } 7157d63899aSWei Huang out: 7167d63899aSWei Huang clear_interrupt(ctx); 7177d63899aSWei Huang return ret; 7187d63899aSWei Huang } 7197d63899aSWei Huang 7207d63899aSWei Huang static void send_descriptor(struct dma_afu_ctx *ctx, msgdma_ext_desc *desc) 7217d63899aSWei Huang { 7227d63899aSWei Huang msgdma_status status; 7237d63899aSWei Huang uint64_t fpga_queue_full = 0; 7247d63899aSWei Huang 7257d63899aSWei Huang if (!ctx) 7267d63899aSWei Huang return; 7277d63899aSWei Huang 7287d63899aSWei Huang if (ctx->verbose) { 7297d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("descriptor.rd_address = 0x%x%08x", 7307d63899aSWei Huang desc->rd_address_ext, desc->rd_address); 7317d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("descriptor.wr_address = 0x%x%08x", 7327d63899aSWei Huang desc->wr_address_ext, desc->wr_address); 7337d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("descriptor.len = %u", desc->len); 7347d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("descriptor.wr_burst_count = %u", 7357d63899aSWei Huang desc->wr_burst_count); 7367d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("descriptor.rd_burst_count = %u", 7377d63899aSWei Huang desc->rd_burst_count); 7387d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("descriptor.wr_stride %u", desc->wr_stride); 7397d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("descriptor.rd_stride %u", desc->rd_stride); 7407d63899aSWei Huang } 7417d63899aSWei Huang 7427d63899aSWei Huang do { 7437d63899aSWei Huang status.csr = rte_read32(CSR_STATUS(ctx->csr_addr)); 7447d63899aSWei Huang if (fpga_queue_full++ > 100000000) { 7457d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("DMA queue full retry"); 7467d63899aSWei Huang fpga_queue_full = 0; 7477d63899aSWei Huang } 7487d63899aSWei Huang } while (status.desc_buf_full); 7497d63899aSWei Huang 7507d63899aSWei Huang blk_write64((uint64_t *)ctx->desc_addr, (uint64_t *)desc, 7517d63899aSWei Huang sizeof(*desc)); 7527d63899aSWei Huang } 7537d63899aSWei Huang 7547d63899aSWei Huang static int do_dma(struct dma_afu_ctx *ctx, uint64_t dst, uint64_t src, 7557d63899aSWei Huang int count, int is_last_desc, fpga_dma_type type, int intr_en) 7567d63899aSWei Huang { 7577d63899aSWei Huang msgdma_ext_desc *desc = NULL; 7587d63899aSWei Huang int alignment_offset = 0; 7597d63899aSWei Huang int segment_size = 0; 7607d63899aSWei Huang 7617d63899aSWei Huang if (!ctx) 7627d63899aSWei Huang return -EINVAL; 7637d63899aSWei Huang 7647d63899aSWei Huang /* src, dst and count must be 64-byte aligned */ 7657d63899aSWei Huang if (!IS_DMA_ALIGNED(src) || !IS_DMA_ALIGNED(dst) || 7667d63899aSWei Huang !IS_DMA_ALIGNED(count)) 7677d63899aSWei Huang return -EINVAL; 7687d63899aSWei Huang memset(ctx->desc_buf, 0, sizeof(msgdma_ext_desc)); 7697d63899aSWei Huang 7707d63899aSWei Huang /* these fields are fixed for all DMA transfers */ 7717d63899aSWei Huang desc = ctx->desc_buf; 7727d63899aSWei Huang desc->seq_num = 0; 7737d63899aSWei Huang desc->wr_stride = 1; 7747d63899aSWei Huang desc->rd_stride = 1; 7757d63899aSWei Huang desc->control.go = 1; 7767d63899aSWei Huang if (intr_en) 7777d63899aSWei Huang desc->control.transfer_irq_en = 1; 7787d63899aSWei Huang else 7797d63899aSWei Huang desc->control.transfer_irq_en = 0; 7807d63899aSWei Huang 7817d63899aSWei Huang if (!is_last_desc) 7827d63899aSWei Huang desc->control.early_done_en = 1; 7837d63899aSWei Huang else 7847d63899aSWei Huang desc->control.early_done_en = 0; 7857d63899aSWei Huang 7867d63899aSWei Huang if (type == FPGA_TO_FPGA) { 7877d63899aSWei Huang desc->rd_address = src & DMA_MASK_32_BIT; 7887d63899aSWei Huang desc->wr_address = dst & DMA_MASK_32_BIT; 7897d63899aSWei Huang desc->len = count; 7907d63899aSWei Huang desc->wr_burst_count = 4; 7917d63899aSWei Huang desc->rd_burst_count = 4; 7927d63899aSWei Huang desc->rd_address_ext = (src >> 32) & DMA_MASK_32_BIT; 7937d63899aSWei Huang desc->wr_address_ext = (dst >> 32) & DMA_MASK_32_BIT; 7947d63899aSWei Huang send_descriptor(ctx, desc); 7957d63899aSWei Huang } else { 7967d63899aSWei Huang /* check CCIP (host) address is aligned to 4CL (256B) */ 7977d63899aSWei Huang alignment_offset = (type == HOST_TO_FPGA) 7987d63899aSWei Huang ? (src % CCIP_ALIGN_BYTES) : (dst % CCIP_ALIGN_BYTES); 7997d63899aSWei Huang /* performing a short transfer to get aligned */ 8007d63899aSWei Huang if (alignment_offset != 0) { 8017d63899aSWei Huang desc->rd_address = src & DMA_MASK_32_BIT; 8027d63899aSWei Huang desc->wr_address = dst & DMA_MASK_32_BIT; 8037d63899aSWei Huang desc->wr_burst_count = 1; 8047d63899aSWei Huang desc->rd_burst_count = 1; 8057d63899aSWei Huang desc->rd_address_ext = (src >> 32) & DMA_MASK_32_BIT; 8067d63899aSWei Huang desc->wr_address_ext = (dst >> 32) & DMA_MASK_32_BIT; 8077d63899aSWei Huang /* count isn't large enough to hit next 4CL boundary */ 8087d63899aSWei Huang if ((CCIP_ALIGN_BYTES - alignment_offset) >= count) { 8097d63899aSWei Huang segment_size = count; 8107d63899aSWei Huang count = 0; 8117d63899aSWei Huang } else { 8127d63899aSWei Huang segment_size = CCIP_ALIGN_BYTES 8137d63899aSWei Huang - alignment_offset; 8147d63899aSWei Huang src += segment_size; 8157d63899aSWei Huang dst += segment_size; 8167d63899aSWei Huang count -= segment_size; 8177d63899aSWei Huang desc->control.transfer_irq_en = 0; 8187d63899aSWei Huang } 8197d63899aSWei Huang /* post short transfer to align to a 4CL (256 byte) */ 8207d63899aSWei Huang desc->len = segment_size; 8217d63899aSWei Huang send_descriptor(ctx, desc); 8227d63899aSWei Huang } 8237d63899aSWei Huang /* at this point we are 4CL (256 byte) aligned */ 8247d63899aSWei Huang if (count >= CCIP_ALIGN_BYTES) { 8257d63899aSWei Huang desc->rd_address = src & DMA_MASK_32_BIT; 8267d63899aSWei Huang desc->wr_address = dst & DMA_MASK_32_BIT; 8277d63899aSWei Huang desc->wr_burst_count = 4; 8287d63899aSWei Huang desc->rd_burst_count = 4; 8297d63899aSWei Huang desc->rd_address_ext = (src >> 32) & DMA_MASK_32_BIT; 8307d63899aSWei Huang desc->wr_address_ext = (dst >> 32) & DMA_MASK_32_BIT; 8317d63899aSWei Huang /* buffer ends on 4CL boundary */ 8327d63899aSWei Huang if ((count % CCIP_ALIGN_BYTES) == 0) { 8337d63899aSWei Huang segment_size = count; 8347d63899aSWei Huang count = 0; 8357d63899aSWei Huang } else { 8367d63899aSWei Huang segment_size = count 8377d63899aSWei Huang - (count % CCIP_ALIGN_BYTES); 8387d63899aSWei Huang src += segment_size; 8397d63899aSWei Huang dst += segment_size; 8407d63899aSWei Huang count -= segment_size; 8417d63899aSWei Huang desc->control.transfer_irq_en = 0; 8427d63899aSWei Huang } 8437d63899aSWei Huang desc->len = segment_size; 8447d63899aSWei Huang send_descriptor(ctx, desc); 8457d63899aSWei Huang } 8467d63899aSWei Huang /* post short transfer to handle the remainder */ 8477d63899aSWei Huang if (count > 0) { 8487d63899aSWei Huang desc->rd_address = src & DMA_MASK_32_BIT; 8497d63899aSWei Huang desc->wr_address = dst & DMA_MASK_32_BIT; 8507d63899aSWei Huang desc->len = count; 8517d63899aSWei Huang desc->wr_burst_count = 1; 8527d63899aSWei Huang desc->rd_burst_count = 1; 8537d63899aSWei Huang desc->rd_address_ext = (src >> 32) & DMA_MASK_32_BIT; 8547d63899aSWei Huang desc->wr_address_ext = (dst >> 32) & DMA_MASK_32_BIT; 8557d63899aSWei Huang if (intr_en) 8567d63899aSWei Huang desc->control.transfer_irq_en = 1; 8577d63899aSWei Huang send_descriptor(ctx, desc); 8587d63899aSWei Huang } 8597d63899aSWei Huang } 8607d63899aSWei Huang 8617d63899aSWei Huang return 0; 8627d63899aSWei Huang } 8637d63899aSWei Huang 8647d63899aSWei Huang static int issue_magic(struct dma_afu_ctx *ctx) 8657d63899aSWei Huang { 8667d63899aSWei Huang *(ctx->magic_buf) = 0ULL; 8677d63899aSWei Huang return do_dma(ctx, DMA_WF_HOST_ADDR(ctx->magic_iova), 8687d63899aSWei Huang DMA_WF_MAGIC_ROM, 64, 1, FPGA_TO_HOST, 1); 8697d63899aSWei Huang } 8707d63899aSWei Huang 8717d63899aSWei Huang static void wait_magic(struct dma_afu_ctx *ctx) 8727d63899aSWei Huang { 8737d63899aSWei Huang int magic_timeout = 0; 8747d63899aSWei Huang 8757d63899aSWei Huang if (!ctx) 8767d63899aSWei Huang return; 8777d63899aSWei Huang 8787d63899aSWei Huang poll_interrupt(ctx); 8797d63899aSWei Huang while (*(ctx->magic_buf) != DMA_WF_MAGIC) { 8807d63899aSWei Huang if (magic_timeout++ > 1000) { 8817d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("DMA magic operation timeout"); 8827d63899aSWei Huang magic_timeout = 0; 8837d63899aSWei Huang break; 8847d63899aSWei Huang } 8857d63899aSWei Huang } 8867d63899aSWei Huang *(ctx->magic_buf) = 0ULL; 8877d63899aSWei Huang } 8887d63899aSWei Huang 8897d63899aSWei Huang static int dma_tx_buf(struct dma_afu_ctx *ctx, uint64_t dst, uint64_t src, 8907d63899aSWei Huang uint64_t chunk, int is_last_chunk, int *intr_issued) 8917d63899aSWei Huang { 8927d63899aSWei Huang int intr_en = 0; 8937d63899aSWei Huang int ret = 0; 8947d63899aSWei Huang 8957d63899aSWei Huang if (!ctx || !intr_issued) 8967d63899aSWei Huang return -EINVAL; 8977d63899aSWei Huang 8987d63899aSWei Huang src += chunk * ctx->dma_buf_size; 8997d63899aSWei Huang dst += chunk * ctx->dma_buf_size; 9007d63899aSWei Huang 9017d63899aSWei Huang if (((chunk % HALF_DMA_BUF) == (HALF_DMA_BUF - 1)) || is_last_chunk) { 9027d63899aSWei Huang if (*intr_issued) { 9037d63899aSWei Huang ret = poll_interrupt(ctx); 9047d63899aSWei Huang if (ret) 9057d63899aSWei Huang return ret; 9067d63899aSWei Huang } 9077d63899aSWei Huang intr_en = 1; 9087d63899aSWei Huang } 9097d63899aSWei Huang 9107d63899aSWei Huang chunk %= NUM_DMA_BUF; 9117d63899aSWei Huang rte_memcpy(ctx->dma_buf[chunk], (void *)(uintptr_t)src, 9127d63899aSWei Huang ctx->dma_buf_size); 9137d63899aSWei Huang ret = do_dma(ctx, dst, DMA_HOST_ADDR(ctx->dma_iova[chunk]), 9147d63899aSWei Huang ctx->dma_buf_size, 0, HOST_TO_FPGA, intr_en); 9157d63899aSWei Huang if (intr_en) 9167d63899aSWei Huang *intr_issued = 1; 9177d63899aSWei Huang 9187d63899aSWei Huang return ret; 9197d63899aSWei Huang } 9207d63899aSWei Huang 9217d63899aSWei Huang static int dma_host_to_fpga(struct dma_afu_ctx *ctx, uint64_t dst, uint64_t src, 9227d63899aSWei Huang size_t count) 9237d63899aSWei Huang { 9247d63899aSWei Huang uint64_t i = 0; 9257d63899aSWei Huang uint64_t count_left = count; 9267d63899aSWei Huang uint64_t aligned_addr = 0; 9277d63899aSWei Huang uint64_t align_bytes = 0; 9287d63899aSWei Huang uint64_t dma_chunks = 0; 9297d63899aSWei Huang uint64_t dma_tx_bytes = 0; 9307d63899aSWei Huang uint64_t offset = 0; 9317d63899aSWei Huang int issued_intr = 0; 9327d63899aSWei Huang int ret = 0; 9337d63899aSWei Huang 9347d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" ---> 0x%"PRIx64" (%zu)", src, dst, 9357d63899aSWei Huang count); 9367d63899aSWei Huang 9377d63899aSWei Huang if (!ctx) 9387d63899aSWei Huang return -EINVAL; 9397d63899aSWei Huang 9407d63899aSWei Huang if (!IS_DMA_ALIGNED(dst)) { 9417d63899aSWei Huang if (count_left < DMA_ALIGN_BYTES) 9427d63899aSWei Huang return ase_host_to_fpga(ctx, &dst, &src, count_left); 9437d63899aSWei Huang 9447d63899aSWei Huang aligned_addr = ((dst / DMA_ALIGN_BYTES) + 1) 9457d63899aSWei Huang * DMA_ALIGN_BYTES; 9467d63899aSWei Huang align_bytes = aligned_addr - dst; 9477d63899aSWei Huang ret = ase_host_to_fpga(ctx, &dst, &src, align_bytes); 9487d63899aSWei Huang if (ret) 9497d63899aSWei Huang return ret; 9507d63899aSWei Huang count_left = count_left - align_bytes; 9517d63899aSWei Huang } 9527d63899aSWei Huang 9537d63899aSWei Huang if (count_left) { 9547d63899aSWei Huang dma_chunks = count_left / ctx->dma_buf_size; 9557d63899aSWei Huang offset = dma_chunks * ctx->dma_buf_size; 9567d63899aSWei Huang count_left -= offset; 9577d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" ---> 0x%"PRIx64 9587d63899aSWei Huang " (%"PRIu64"...0x%"PRIx64")", 9597d63899aSWei Huang src, dst, dma_chunks, count_left); 9607d63899aSWei Huang for (i = 0; i < dma_chunks; i++) { 9617d63899aSWei Huang ret = dma_tx_buf(ctx, dst, src, i, 9627d63899aSWei Huang i == (dma_chunks - 1), &issued_intr); 9637d63899aSWei Huang if (ret) 9647d63899aSWei Huang return ret; 9657d63899aSWei Huang } 9667d63899aSWei Huang 9677d63899aSWei Huang if (issued_intr) { 9687d63899aSWei Huang ret = poll_interrupt(ctx); 9697d63899aSWei Huang if (ret) 9707d63899aSWei Huang return ret; 9717d63899aSWei Huang } 9727d63899aSWei Huang 9737d63899aSWei Huang if (count_left) { 9747d63899aSWei Huang i = count_left / DMA_ALIGN_BYTES; 9757d63899aSWei Huang if (i > 0) { 9767d63899aSWei Huang dma_tx_bytes = i * DMA_ALIGN_BYTES; 9777d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("left over 0x%"PRIx64" to DMA", 9787d63899aSWei Huang dma_tx_bytes); 9797d63899aSWei Huang rte_memcpy(ctx->dma_buf[0], 9807d63899aSWei Huang (void *)(uintptr_t)(src + offset), 9817d63899aSWei Huang dma_tx_bytes); 9827d63899aSWei Huang ret = do_dma(ctx, dst + offset, 9837d63899aSWei Huang DMA_HOST_ADDR(ctx->dma_iova[0]), 9847d63899aSWei Huang dma_tx_bytes, 1, HOST_TO_FPGA, 1); 9857d63899aSWei Huang if (ret) 9867d63899aSWei Huang return ret; 9877d63899aSWei Huang ret = poll_interrupt(ctx); 9887d63899aSWei Huang if (ret) 9897d63899aSWei Huang return ret; 9907d63899aSWei Huang } 9917d63899aSWei Huang 9927d63899aSWei Huang count_left -= dma_tx_bytes; 9937d63899aSWei Huang if (count_left) { 9947d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("left over 0x%"PRIx64" to ASE", 9957d63899aSWei Huang count_left); 9967d63899aSWei Huang dst += offset + dma_tx_bytes; 9977d63899aSWei Huang src += offset + dma_tx_bytes; 9987d63899aSWei Huang ret = ase_host_to_fpga(ctx, &dst, &src, 9997d63899aSWei Huang count_left); 10007d63899aSWei Huang } 10017d63899aSWei Huang } 10027d63899aSWei Huang } 10037d63899aSWei Huang 10047d63899aSWei Huang return ret; 10057d63899aSWei Huang } 10067d63899aSWei Huang 10077d63899aSWei Huang static int dma_rx_buf(struct dma_afu_ctx *ctx, uint64_t dst, uint64_t src, 10087d63899aSWei Huang uint64_t chunk, int is_last_chunk, uint64_t *rx_count, int *wf_issued) 10097d63899aSWei Huang { 10107d63899aSWei Huang uint64_t i = chunk % NUM_DMA_BUF; 10117d63899aSWei Huang uint64_t n = *rx_count; 10127d63899aSWei Huang uint64_t num_pending = 0; 10137d63899aSWei Huang int ret = 0; 10147d63899aSWei Huang 10157d63899aSWei Huang if (!ctx || !wf_issued) 10167d63899aSWei Huang return -EINVAL; 10177d63899aSWei Huang 10187d63899aSWei Huang ret = do_dma(ctx, DMA_HOST_ADDR(ctx->dma_iova[i]), 10197d63899aSWei Huang src + chunk * ctx->dma_buf_size, 10207d63899aSWei Huang ctx->dma_buf_size, 1, FPGA_TO_HOST, 0); 10217d63899aSWei Huang if (ret) 10227d63899aSWei Huang return ret; 10237d63899aSWei Huang 10247d63899aSWei Huang num_pending = chunk - n + 1; 10257d63899aSWei Huang if (num_pending == HALF_DMA_BUF) { 10267d63899aSWei Huang ret = issue_magic(ctx); 10277d63899aSWei Huang if (ret) { 10287d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("Magic issue failed"); 10297d63899aSWei Huang return ret; 10307d63899aSWei Huang } 10317d63899aSWei Huang *wf_issued = 1; 10327d63899aSWei Huang } 10337d63899aSWei Huang 10347d63899aSWei Huang if ((num_pending > (NUM_DMA_BUF - 1)) || is_last_chunk) { 10357d63899aSWei Huang if (*wf_issued) { 10367d63899aSWei Huang wait_magic(ctx); 10377d63899aSWei Huang for (i = 0; i < HALF_DMA_BUF; i++) { 10387d63899aSWei Huang rte_memcpy((void *)(uintptr_t)(dst + 10397d63899aSWei Huang n * ctx->dma_buf_size), 10407d63899aSWei Huang ctx->dma_buf[n % NUM_DMA_BUF], 10417d63899aSWei Huang ctx->dma_buf_size); 10427d63899aSWei Huang n++; 10437d63899aSWei Huang } 10447d63899aSWei Huang *wf_issued = 0; 10457d63899aSWei Huang *rx_count = n; 10467d63899aSWei Huang } 10477d63899aSWei Huang ret = issue_magic(ctx); 10487d63899aSWei Huang if (ret) { 10497d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("Magic issue failed"); 10507d63899aSWei Huang return ret; 10517d63899aSWei Huang } 10527d63899aSWei Huang *wf_issued = 1; 10537d63899aSWei Huang } 10547d63899aSWei Huang 10557d63899aSWei Huang return ret; 10567d63899aSWei Huang } 10577d63899aSWei Huang 10587d63899aSWei Huang static int dma_fpga_to_host(struct dma_afu_ctx *ctx, uint64_t dst, uint64_t src, 10597d63899aSWei Huang size_t count) 10607d63899aSWei Huang { 10617d63899aSWei Huang uint64_t i = 0; 10627d63899aSWei Huang uint64_t count_left = count; 10637d63899aSWei Huang uint64_t aligned_addr = 0; 10647d63899aSWei Huang uint64_t align_bytes = 0; 10657d63899aSWei Huang uint64_t dma_chunks = 0; 10667d63899aSWei Huang uint64_t pending_buf = 0; 10677d63899aSWei Huang uint64_t dma_rx_bytes = 0; 10687d63899aSWei Huang uint64_t offset = 0; 10697d63899aSWei Huang int wf_issued = 0; 10707d63899aSWei Huang int ret = 0; 10717d63899aSWei Huang 10727d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" ---> 0x%"PRIx64" (%zu)", src, dst, 10737d63899aSWei Huang count); 10747d63899aSWei Huang 10757d63899aSWei Huang if (!ctx) 10767d63899aSWei Huang return -EINVAL; 10777d63899aSWei Huang 10787d63899aSWei Huang if (!IS_DMA_ALIGNED(src)) { 10797d63899aSWei Huang if (count_left < DMA_ALIGN_BYTES) 10807d63899aSWei Huang return ase_fpga_to_host(ctx, &src, &dst, count_left); 10817d63899aSWei Huang 10827d63899aSWei Huang aligned_addr = ((src / DMA_ALIGN_BYTES) + 1) 10837d63899aSWei Huang * DMA_ALIGN_BYTES; 10847d63899aSWei Huang align_bytes = aligned_addr - src; 10857d63899aSWei Huang ret = ase_fpga_to_host(ctx, &src, &dst, align_bytes); 10867d63899aSWei Huang if (ret) 10877d63899aSWei Huang return ret; 10887d63899aSWei Huang count_left = count_left - align_bytes; 10897d63899aSWei Huang } 10907d63899aSWei Huang 10917d63899aSWei Huang if (count_left) { 10927d63899aSWei Huang dma_chunks = count_left / ctx->dma_buf_size; 10937d63899aSWei Huang offset = dma_chunks * ctx->dma_buf_size; 10947d63899aSWei Huang count_left -= offset; 10957d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" ---> 0x%"PRIx64 10967d63899aSWei Huang " (%"PRIu64"...0x%"PRIx64")", 10977d63899aSWei Huang src, dst, dma_chunks, count_left); 10987d63899aSWei Huang for (i = 0; i < dma_chunks; i++) { 10997d63899aSWei Huang ret = dma_rx_buf(ctx, dst, src, i, 11007d63899aSWei Huang i == (dma_chunks - 1), 11017d63899aSWei Huang &pending_buf, &wf_issued); 11027d63899aSWei Huang if (ret) 11037d63899aSWei Huang return ret; 11047d63899aSWei Huang } 11057d63899aSWei Huang 11067d63899aSWei Huang if (wf_issued) 11077d63899aSWei Huang wait_magic(ctx); 11087d63899aSWei Huang 11097d63899aSWei Huang /* clear out final dma memcpy operations */ 11107d63899aSWei Huang while (pending_buf < dma_chunks) { 11117d63899aSWei Huang /* constant size transfer; no length check required */ 11127d63899aSWei Huang rte_memcpy((void *)(uintptr_t)(dst + 11137d63899aSWei Huang pending_buf * ctx->dma_buf_size), 11147d63899aSWei Huang ctx->dma_buf[pending_buf % NUM_DMA_BUF], 11157d63899aSWei Huang ctx->dma_buf_size); 11167d63899aSWei Huang pending_buf++; 11177d63899aSWei Huang } 11187d63899aSWei Huang 11197d63899aSWei Huang if (count_left > 0) { 11207d63899aSWei Huang i = count_left / DMA_ALIGN_BYTES; 11217d63899aSWei Huang if (i > 0) { 11227d63899aSWei Huang dma_rx_bytes = i * DMA_ALIGN_BYTES; 11237d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("left over 0x%"PRIx64" to DMA", 11247d63899aSWei Huang dma_rx_bytes); 11257d63899aSWei Huang ret = do_dma(ctx, 11267d63899aSWei Huang DMA_HOST_ADDR(ctx->dma_iova[0]), 11277d63899aSWei Huang src + offset, 11287d63899aSWei Huang dma_rx_bytes, 1, FPGA_TO_HOST, 0); 11297d63899aSWei Huang if (ret) 11307d63899aSWei Huang return ret; 11317d63899aSWei Huang ret = issue_magic(ctx); 11327d63899aSWei Huang if (ret) 11337d63899aSWei Huang return ret; 11347d63899aSWei Huang wait_magic(ctx); 11357d63899aSWei Huang rte_memcpy((void *)(uintptr_t)(dst + offset), 11367d63899aSWei Huang ctx->dma_buf[0], dma_rx_bytes); 11377d63899aSWei Huang } 11387d63899aSWei Huang 11397d63899aSWei Huang count_left -= dma_rx_bytes; 11407d63899aSWei Huang if (count_left) { 11417d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("left over 0x%"PRIx64" to ASE", 11427d63899aSWei Huang count_left); 11437d63899aSWei Huang dst += offset + dma_rx_bytes; 11447d63899aSWei Huang src += offset + dma_rx_bytes; 11457d63899aSWei Huang ret = ase_fpga_to_host(ctx, &src, &dst, 11467d63899aSWei Huang count_left); 11477d63899aSWei Huang } 11487d63899aSWei Huang } 11497d63899aSWei Huang } 11507d63899aSWei Huang 11517d63899aSWei Huang return ret; 11527d63899aSWei Huang } 11537d63899aSWei Huang 11547d63899aSWei Huang static int dma_fpga_to_fpga(struct dma_afu_ctx *ctx, uint64_t dst, uint64_t src, 11557d63899aSWei Huang size_t count) 11567d63899aSWei Huang { 11577d63899aSWei Huang uint64_t i = 0; 11587d63899aSWei Huang uint64_t count_left = count; 11597d63899aSWei Huang uint64_t dma_chunks = 0; 11607d63899aSWei Huang uint64_t offset = 0; 1161099da897SWei Huang uint64_t tx_chunks = 0; 11627d63899aSWei Huang uint64_t *tmp_buf = NULL; 11637d63899aSWei Huang int ret = 0; 11647d63899aSWei Huang 11657d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" ---> 0x%"PRIx64" (%zu)", src, dst, 11667d63899aSWei Huang count); 11677d63899aSWei Huang 11687d63899aSWei Huang if (!ctx) 11697d63899aSWei Huang return -EINVAL; 11707d63899aSWei Huang 11717d63899aSWei Huang if (IS_DMA_ALIGNED(dst) && IS_DMA_ALIGNED(src) 11727d63899aSWei Huang && IS_DMA_ALIGNED(count_left)) { 11737d63899aSWei Huang dma_chunks = count_left / ctx->dma_buf_size; 11747d63899aSWei Huang offset = dma_chunks * ctx->dma_buf_size; 11757d63899aSWei Huang count_left -= offset; 11767d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" ---> 0x%"PRIx64 11777d63899aSWei Huang " (%"PRIu64"...0x%"PRIx64")", 11787d63899aSWei Huang src, dst, dma_chunks, count_left); 11797d63899aSWei Huang for (i = 0; i < dma_chunks; i++) { 11807d63899aSWei Huang ret = do_dma(ctx, dst + i * ctx->dma_buf_size, 11817d63899aSWei Huang src + i * ctx->dma_buf_size, 11827d63899aSWei Huang ctx->dma_buf_size, 0, FPGA_TO_FPGA, 0); 11837d63899aSWei Huang if (ret) 11847d63899aSWei Huang return ret; 11857d63899aSWei Huang if ((((i + 1) % NUM_DMA_BUF) == 0) || 11867d63899aSWei Huang (i == (dma_chunks - 1))) { 11877d63899aSWei Huang ret = issue_magic(ctx); 11887d63899aSWei Huang if (ret) 11897d63899aSWei Huang return ret; 11907d63899aSWei Huang wait_magic(ctx); 11917d63899aSWei Huang } 11927d63899aSWei Huang } 11937d63899aSWei Huang 11947d63899aSWei Huang if (count_left > 0) { 11957d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("left over 0x%"PRIx64" to DMA", count_left); 11967d63899aSWei Huang ret = do_dma(ctx, dst + offset, src + offset, 11977d63899aSWei Huang count_left, 1, FPGA_TO_FPGA, 0); 11987d63899aSWei Huang if (ret) 11997d63899aSWei Huang return ret; 12007d63899aSWei Huang ret = issue_magic(ctx); 12017d63899aSWei Huang if (ret) 12027d63899aSWei Huang return ret; 12037d63899aSWei Huang wait_magic(ctx); 12047d63899aSWei Huang } 12057d63899aSWei Huang } else { 12067d63899aSWei Huang if ((src < dst) && (src + count_left > dst)) { 12077d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Overlapping: 0x%"PRIx64 12087d63899aSWei Huang " -> 0x%"PRIx64" (0x%"PRIx64")", 12097d63899aSWei Huang src, dst, count_left); 12107d63899aSWei Huang return -EINVAL; 12117d63899aSWei Huang } 12127d63899aSWei Huang tx_chunks = count_left / ctx->dma_buf_size; 12137d63899aSWei Huang offset = tx_chunks * ctx->dma_buf_size; 12147d63899aSWei Huang count_left -= offset; 12157d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("0x%"PRIx64" --> 0x%"PRIx64 1216099da897SWei Huang " (%"PRIu64"...0x%"PRIx64")", 12177d63899aSWei Huang src, dst, tx_chunks, count_left); 12187d63899aSWei Huang tmp_buf = (uint64_t *)rte_malloc(NULL, ctx->dma_buf_size, 12197d63899aSWei Huang DMA_ALIGN_BYTES); 12207d63899aSWei Huang for (i = 0; i < tx_chunks; i++) { 12217d63899aSWei Huang ret = dma_fpga_to_host(ctx, (uint64_t)tmp_buf, 12227d63899aSWei Huang src + i * ctx->dma_buf_size, 12237d63899aSWei Huang ctx->dma_buf_size); 12247d63899aSWei Huang if (ret) 12257d63899aSWei Huang goto free_buf; 12267d63899aSWei Huang ret = dma_host_to_fpga(ctx, 12277d63899aSWei Huang dst + i * ctx->dma_buf_size, 12287d63899aSWei Huang (uint64_t)tmp_buf, ctx->dma_buf_size); 12297d63899aSWei Huang if (ret) 12307d63899aSWei Huang goto free_buf; 12317d63899aSWei Huang } 12327d63899aSWei Huang 12337d63899aSWei Huang if (count_left > 0) { 12347d63899aSWei Huang ret = dma_fpga_to_host(ctx, (uint64_t)tmp_buf, 12357d63899aSWei Huang src + offset, count_left); 12367d63899aSWei Huang if (ret) 12377d63899aSWei Huang goto free_buf; 12387d63899aSWei Huang ret = dma_host_to_fpga(ctx, dst + offset, 12397d63899aSWei Huang (uint64_t)tmp_buf, count_left); 12407d63899aSWei Huang if (ret) 12417d63899aSWei Huang goto free_buf; 12427d63899aSWei Huang } 12437d63899aSWei Huang free_buf: 12447d63899aSWei Huang rte_free(tmp_buf); 12457d63899aSWei Huang } 12467d63899aSWei Huang 12477d63899aSWei Huang return ret; 12487d63899aSWei Huang } 12497d63899aSWei Huang 12507d63899aSWei Huang static int dma_transfer_sync(struct dma_afu_ctx *ctx, uint64_t dst, 12517d63899aSWei Huang uint64_t src, size_t count, fpga_dma_type type) 12527d63899aSWei Huang { 12537d63899aSWei Huang int ret = 0; 12547d63899aSWei Huang 12557d63899aSWei Huang if (!ctx) 12567d63899aSWei Huang return -EINVAL; 12577d63899aSWei Huang 12587d63899aSWei Huang if (type == HOST_TO_FPGA) 12597d63899aSWei Huang ret = dma_host_to_fpga(ctx, dst, src, count); 12607d63899aSWei Huang else if (type == FPGA_TO_HOST) 12617d63899aSWei Huang ret = dma_fpga_to_host(ctx, dst, src, count); 12627d63899aSWei Huang else if (type == FPGA_TO_FPGA) 12637d63899aSWei Huang ret = dma_fpga_to_fpga(ctx, dst, src, count); 12647d63899aSWei Huang else 12657d63899aSWei Huang return -EINVAL; 12667d63899aSWei Huang 12677d63899aSWei Huang return ret; 12687d63899aSWei Huang } 12697d63899aSWei Huang 12707d63899aSWei Huang static double get_duration(struct timespec start, struct timespec end) 12717d63899aSWei Huang { 12727d63899aSWei Huang uint64_t diff = 1000000000L * (end.tv_sec - start.tv_sec) 12737d63899aSWei Huang + end.tv_nsec - start.tv_nsec; 12747d63899aSWei Huang return (double)diff / (double)1000000000L; 12757d63899aSWei Huang } 12767d63899aSWei Huang 12777d63899aSWei Huang #define SWEEP_ITERS 1 12787d63899aSWei Huang static int sweep_test(struct dma_afu_ctx *ctx, uint32_t length, 12797d63899aSWei Huang uint64_t ddr_offset, uint64_t buf_offset, uint64_t size_decrement) 12807d63899aSWei Huang { 12817d63899aSWei Huang struct timespec start, end; 12827d63899aSWei Huang uint64_t test_size = 0; 12837d63899aSWei Huang uint64_t *dma_buf_ptr = NULL; 12847d63899aSWei Huang double throughput, total_time = 0.0; 12857d63899aSWei Huang int i = 0; 12867d63899aSWei Huang int ret = 0; 12877d63899aSWei Huang 12887d63899aSWei Huang if (!ctx || !ctx->data_buf || !ctx->ref_buf) { 12897d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Buffer for DMA test is not allocated"); 12907d63899aSWei Huang return -EINVAL; 12917d63899aSWei Huang } 12927d63899aSWei Huang 12937d63899aSWei Huang if (length < (buf_offset + size_decrement)) { 12947d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Test length does not match unaligned parameter"); 12957d63899aSWei Huang return -EINVAL; 12967d63899aSWei Huang } 12977d63899aSWei Huang test_size = length - (buf_offset + size_decrement); 12987d63899aSWei Huang if ((ddr_offset + test_size) > ctx->mem_size) { 12997d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Test is out of DDR memory space"); 13007d63899aSWei Huang return -EINVAL; 13017d63899aSWei Huang } 13027d63899aSWei Huang 13037d63899aSWei Huang dma_buf_ptr = (uint64_t *)((uint8_t *)ctx->data_buf + buf_offset); 13047d63899aSWei Huang printf("Sweep Host %p to FPGA 0x%"PRIx64 13057d63899aSWei Huang " with 0x%"PRIx64" bytes ...\n", 13067d63899aSWei Huang (void *)dma_buf_ptr, ddr_offset, test_size); 13077d63899aSWei Huang 13087d63899aSWei Huang for (i = 0; i < SWEEP_ITERS; i++) { 13097d63899aSWei Huang clock_gettime(CLOCK_MONOTONIC, &start); 13107d63899aSWei Huang ret = dma_transfer_sync(ctx, ddr_offset, (uint64_t)dma_buf_ptr, 13117d63899aSWei Huang test_size, HOST_TO_FPGA); 13127d63899aSWei Huang clock_gettime(CLOCK_MONOTONIC, &end); 13137d63899aSWei Huang if (ret) { 13147d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Failed"); 13157d63899aSWei Huang return ret; 13167d63899aSWei Huang } 13177d63899aSWei Huang total_time += get_duration(start, end); 13187d63899aSWei Huang } 13197d63899aSWei Huang throughput = (test_size * SWEEP_ITERS) / (total_time * 1000000); 13207d63899aSWei Huang printf("Measured bandwidth = %lf MB/s\n", throughput); 13217d63899aSWei Huang 13227d63899aSWei Huang printf("Sweep FPGA 0x%"PRIx64" to Host %p with 0x%"PRIx64" bytes ...\n", 13237d63899aSWei Huang ddr_offset, (void *)dma_buf_ptr, test_size); 13247d63899aSWei Huang 13257d63899aSWei Huang total_time = 0.0; 13267d63899aSWei Huang memset((char *)dma_buf_ptr, 0, test_size); 13277d63899aSWei Huang for (i = 0; i < SWEEP_ITERS; i++) { 13287d63899aSWei Huang clock_gettime(CLOCK_MONOTONIC, &start); 13297d63899aSWei Huang ret = dma_transfer_sync(ctx, (uint64_t)dma_buf_ptr, ddr_offset, 13307d63899aSWei Huang test_size, FPGA_TO_HOST); 13317d63899aSWei Huang clock_gettime(CLOCK_MONOTONIC, &end); 13327d63899aSWei Huang if (ret) { 13337d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Failed"); 13347d63899aSWei Huang return ret; 13357d63899aSWei Huang } 13367d63899aSWei Huang total_time += get_duration(start, end); 13377d63899aSWei Huang } 13387d63899aSWei Huang throughput = (test_size * SWEEP_ITERS) / (total_time * 1000000); 13397d63899aSWei Huang printf("Measured bandwidth = %lf MB/s\n", throughput); 13407d63899aSWei Huang 13417d63899aSWei Huang printf("Verifying buffer ...\n"); 13427d63899aSWei Huang return dma_afu_buf_verify(ctx, test_size); 13437d63899aSWei Huang } 13447d63899aSWei Huang 13457d63899aSWei Huang static int dma_afu_test(struct afu_rawdev *dev) 13467d63899aSWei Huang { 13477d63899aSWei Huang struct n3000_afu_priv *priv = NULL; 13487d63899aSWei Huang struct dma_afu_ctx *ctx = NULL; 13497d63899aSWei Huang struct rte_pmd_afu_dma_cfg *cfg = NULL; 13507d63899aSWei Huang msgdma_ctrl ctrl; 13517d63899aSWei Huang uint64_t offset = 0; 13527d63899aSWei Huang uint32_t i = 0; 13537d63899aSWei Huang int ret = 0; 13547d63899aSWei Huang 13557d63899aSWei Huang if (!dev) 13567d63899aSWei Huang return -EINVAL; 13577d63899aSWei Huang 13587d63899aSWei Huang if (!dev->priv) 13597d63899aSWei Huang return -ENOENT; 13607d63899aSWei Huang 13617d63899aSWei Huang priv = (struct n3000_afu_priv *)dev->priv; 13627d63899aSWei Huang cfg = &priv->dma_cfg; 13637d63899aSWei Huang if (cfg->index >= NUM_N3000_DMA) 13647d63899aSWei Huang return -EINVAL; 13657d63899aSWei Huang ctx = &priv->dma_ctx[cfg->index]; 13667d63899aSWei Huang 13677d63899aSWei Huang ctx->pattern = (int)cfg->pattern; 13687d63899aSWei Huang ctx->verbose = (int)cfg->verbose; 13697d63899aSWei Huang ctx->dma_buf_size = cfg->size; 13707d63899aSWei Huang 13717d63899aSWei Huang ret = dma_afu_buf_alloc(ctx, cfg); 13727d63899aSWei Huang if (ret) 13737d63899aSWei Huang goto free; 13747d63899aSWei Huang 13757d63899aSWei Huang printf("Initialize test buffer\n"); 13767d63899aSWei Huang dma_afu_buf_init(ctx, cfg->length); 13777d63899aSWei Huang 13787d63899aSWei Huang /* enable interrupt */ 13797d63899aSWei Huang ctrl.csr = 0; 13807d63899aSWei Huang ctrl.global_intr_en_mask = 1; 13817d63899aSWei Huang rte_write32(ctrl.csr, CSR_CONTROL(ctx->csr_addr)); 13827d63899aSWei Huang 13837d63899aSWei Huang printf("Host %p to FPGA 0x%x with 0x%x bytes\n", ctx->data_buf, 13847d63899aSWei Huang cfg->offset, cfg->length); 13857d63899aSWei Huang ret = dma_transfer_sync(ctx, cfg->offset, (uint64_t)ctx->data_buf, 13867d63899aSWei Huang cfg->length, HOST_TO_FPGA); 13877d63899aSWei Huang if (ret) { 13887d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Failed to transfer data from host to FPGA"); 13897d63899aSWei Huang goto end; 13907d63899aSWei Huang } 13917d63899aSWei Huang memset(ctx->data_buf, 0, cfg->length); 13927d63899aSWei Huang 13937d63899aSWei Huang printf("FPGA 0x%x to Host %p with 0x%x bytes\n", cfg->offset, 13947d63899aSWei Huang ctx->data_buf, cfg->length); 13957d63899aSWei Huang ret = dma_transfer_sync(ctx, (uint64_t)ctx->data_buf, cfg->offset, 13967d63899aSWei Huang cfg->length, FPGA_TO_HOST); 13977d63899aSWei Huang if (ret) { 13987d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Failed to transfer data from FPGA to host"); 13997d63899aSWei Huang goto end; 14007d63899aSWei Huang } 14017d63899aSWei Huang ret = dma_afu_buf_verify(ctx, cfg->length); 14027d63899aSWei Huang if (ret) 14037d63899aSWei Huang goto end; 14047d63899aSWei Huang 14057d63899aSWei Huang if ((cfg->offset + cfg->length * 2) <= ctx->mem_size) 14067d63899aSWei Huang offset = cfg->offset + cfg->length; 14077d63899aSWei Huang else if (cfg->offset > cfg->length) 14087d63899aSWei Huang offset = 0; 14097d63899aSWei Huang else 14107d63899aSWei Huang goto end; 14117d63899aSWei Huang 14127d63899aSWei Huang printf("FPGA 0x%x to FPGA 0x%"PRIx64" with 0x%x bytes\n", 14137d63899aSWei Huang cfg->offset, offset, cfg->length); 14147d63899aSWei Huang ret = dma_transfer_sync(ctx, offset, cfg->offset, cfg->length, 14157d63899aSWei Huang FPGA_TO_FPGA); 14167d63899aSWei Huang if (ret) { 14177d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Failed to transfer data from FPGA to FPGA"); 14187d63899aSWei Huang goto end; 14197d63899aSWei Huang } 14207d63899aSWei Huang 14217d63899aSWei Huang printf("FPGA 0x%"PRIx64" to Host %p with 0x%x bytes\n", offset, 14227d63899aSWei Huang ctx->data_buf, cfg->length); 14237d63899aSWei Huang ret = dma_transfer_sync(ctx, (uint64_t)ctx->data_buf, offset, 14247d63899aSWei Huang cfg->length, FPGA_TO_HOST); 14257d63899aSWei Huang if (ret) { 14267d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Failed to transfer data from FPGA to host"); 14277d63899aSWei Huang goto end; 14287d63899aSWei Huang } 14297d63899aSWei Huang ret = dma_afu_buf_verify(ctx, cfg->length); 14307d63899aSWei Huang if (ret) 14317d63899aSWei Huang goto end; 14327d63899aSWei Huang 14337d63899aSWei Huang printf("Sweep with aligned address and size\n"); 14347d63899aSWei Huang ret = sweep_test(ctx, cfg->length, cfg->offset, 0, 0); 14357d63899aSWei Huang if (ret) 14367d63899aSWei Huang goto end; 14377d63899aSWei Huang 14387d63899aSWei Huang if (cfg->unaligned) { 14397d63899aSWei Huang printf("Sweep with unaligned address and size\n"); 14407d63899aSWei Huang struct unaligned_set { 14417d63899aSWei Huang uint64_t addr_offset; 14427d63899aSWei Huang uint64_t size_dec; 14437d63899aSWei Huang } param[] = {{61, 5}, {3, 0}, {7, 3}, {0, 3}, {0, 61}, {0, 7}}; 14447d63899aSWei Huang for (i = 0; i < ARRAY_SIZE(param); i++) { 14457d63899aSWei Huang ret = sweep_test(ctx, cfg->length, cfg->offset, 14467d63899aSWei Huang param[i].addr_offset, param[i].size_dec); 14477d63899aSWei Huang if (ret) 14487d63899aSWei Huang break; 14497d63899aSWei Huang } 14507d63899aSWei Huang } 14517d63899aSWei Huang 14527d63899aSWei Huang end: 14537d63899aSWei Huang /* disable interrupt */ 14547d63899aSWei Huang ctrl.global_intr_en_mask = 0; 14557d63899aSWei Huang rte_write32(ctrl.csr, CSR_CONTROL(ctx->csr_addr)); 14567d63899aSWei Huang 14577d63899aSWei Huang free: 14587d63899aSWei Huang dma_afu_buf_free(ctx); 14597d63899aSWei Huang return ret; 14607d63899aSWei Huang } 14617d63899aSWei Huang 14627d63899aSWei Huang static struct rte_pci_device *n3000_afu_get_pci_dev(struct afu_rawdev *dev) 14637d63899aSWei Huang { 14647d63899aSWei Huang struct rte_afu_device *afudev = NULL; 14657d63899aSWei Huang 14667d63899aSWei Huang if (!dev || !dev->rawdev || !dev->rawdev->device) 14677d63899aSWei Huang return NULL; 14687d63899aSWei Huang 14697d63899aSWei Huang afudev = RTE_DEV_TO_AFU(dev->rawdev->device); 14707d63899aSWei Huang if (!afudev->rawdev || !afudev->rawdev->device) 14717d63899aSWei Huang return NULL; 14727d63899aSWei Huang 14737d63899aSWei Huang return RTE_DEV_TO_PCI(afudev->rawdev->device); 14747d63899aSWei Huang } 14757d63899aSWei Huang 14767d63899aSWei Huang #ifdef VFIO_PRESENT 14777d63899aSWei Huang static int dma_afu_set_irqs(struct afu_rawdev *dev, uint32_t vec_start, 14787d63899aSWei Huang uint32_t count, int *efds) 14797d63899aSWei Huang { 14807d63899aSWei Huang struct rte_pci_device *pci_dev = NULL; 14817d63899aSWei Huang struct vfio_irq_set *irq_set = NULL; 14827d63899aSWei Huang int vfio_dev_fd = 0; 14837d63899aSWei Huang size_t sz = 0; 14847d63899aSWei Huang int ret = 0; 14857d63899aSWei Huang 14867d63899aSWei Huang if (!dev || !efds || (count == 0) || (count > MAX_MSIX_VEC)) 14877d63899aSWei Huang return -EINVAL; 14887d63899aSWei Huang 14897d63899aSWei Huang pci_dev = n3000_afu_get_pci_dev(dev); 14907d63899aSWei Huang if (!pci_dev) 14917d63899aSWei Huang return -ENODEV; 14927d63899aSWei Huang vfio_dev_fd = rte_intr_dev_fd_get(pci_dev->intr_handle); 14937d63899aSWei Huang 14947d63899aSWei Huang sz = sizeof(*irq_set) + sizeof(*efds) * count; 14957d63899aSWei Huang irq_set = rte_zmalloc(NULL, sz, 0); 14967d63899aSWei Huang if (!irq_set) 14977d63899aSWei Huang return -ENOMEM; 14987d63899aSWei Huang 14997d63899aSWei Huang irq_set->argsz = (uint32_t)sz; 15007d63899aSWei Huang irq_set->count = count; 15017d63899aSWei Huang irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | 15027d63899aSWei Huang VFIO_IRQ_SET_ACTION_TRIGGER; 15037d63899aSWei Huang irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX; 15047d63899aSWei Huang irq_set->start = vec_start; 15057d63899aSWei Huang 15067d63899aSWei Huang rte_memcpy(&irq_set->data, efds, sizeof(*efds) * count); 15077d63899aSWei Huang ret = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set); 15087d63899aSWei Huang if (ret) 1509*f665790aSDavid Marchand IFPGA_RAWDEV_PMD_ERR("Error enabling MSI-X interrupts"); 15107d63899aSWei Huang 15117d63899aSWei Huang rte_free(irq_set); 15127d63899aSWei Huang return ret; 15137d63899aSWei Huang } 15147d63899aSWei Huang #endif 15157d63899aSWei Huang 15167d63899aSWei Huang static void *n3000_afu_get_port_addr(struct afu_rawdev *dev) 15177d63899aSWei Huang { 15187d63899aSWei Huang struct rte_pci_device *pci_dev = NULL; 15197d63899aSWei Huang uint8_t *addr = NULL; 15207d63899aSWei Huang uint64_t val = 0; 15217d63899aSWei Huang uint32_t bar = 0; 15227d63899aSWei Huang 15237d63899aSWei Huang pci_dev = n3000_afu_get_pci_dev(dev); 15247d63899aSWei Huang if (!pci_dev) 15257d63899aSWei Huang return NULL; 15267d63899aSWei Huang 15277d63899aSWei Huang addr = (uint8_t *)pci_dev->mem_resource[0].addr; 15287d63899aSWei Huang val = rte_read64(addr + PORT_ATTR_REG(dev->port)); 15297d63899aSWei Huang if (!PORT_IMPLEMENTED(val)) { 15307d63899aSWei Huang IFPGA_RAWDEV_PMD_INFO("FIU port %d is not implemented", dev->port); 15317d63899aSWei Huang return NULL; 15327d63899aSWei Huang } 15337d63899aSWei Huang 15347d63899aSWei Huang bar = PORT_BAR(val); 15357d63899aSWei Huang if (bar >= PCI_MAX_RESOURCE) { 15367d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("BAR index %u is out of limit", bar); 15377d63899aSWei Huang return NULL; 15387d63899aSWei Huang } 15397d63899aSWei Huang 15407d63899aSWei Huang addr = (uint8_t *)pci_dev->mem_resource[bar].addr + PORT_OFFSET(val); 15417d63899aSWei Huang return addr; 15427d63899aSWei Huang } 15437d63899aSWei Huang 15447d63899aSWei Huang static int n3000_afu_get_irq_capability(struct afu_rawdev *dev, 15457d63899aSWei Huang uint32_t *vec_start, uint32_t *vec_count) 15467d63899aSWei Huang { 15477d63899aSWei Huang uint8_t *addr = NULL; 15487d63899aSWei Huang uint64_t val = 0; 15497d63899aSWei Huang uint64_t header = 0; 15507d63899aSWei Huang uint64_t next_offset = 0; 15517d63899aSWei Huang 15527d63899aSWei Huang addr = (uint8_t *)n3000_afu_get_port_addr(dev); 15537d63899aSWei Huang if (!addr) 15547d63899aSWei Huang return -ENOENT; 15557d63899aSWei Huang 15567d63899aSWei Huang do { 15577d63899aSWei Huang addr += next_offset; 15587d63899aSWei Huang header = rte_read64(addr); 15597d63899aSWei Huang if ((DFH_TYPE(header) == DFH_TYPE_PRIVATE) && 15607d63899aSWei Huang (DFH_FEATURE_ID(header) == PORT_FEATURE_UINT_ID)) { 15617d63899aSWei Huang val = rte_read64(addr + PORT_UINT_CAP_REG); 15627d63899aSWei Huang if (vec_start) 15637d63899aSWei Huang *vec_start = PORT_VEC_START(val); 15647d63899aSWei Huang if (vec_count) 15657d63899aSWei Huang *vec_count = PORT_VEC_COUNT(val); 15667d63899aSWei Huang return 0; 15677d63899aSWei Huang } 15687d63899aSWei Huang next_offset = DFH_NEXT_OFFSET(header); 15697d63899aSWei Huang if (((next_offset & 0xffff) == 0xffff) || (next_offset == 0)) 15707d63899aSWei Huang break; 15717d63899aSWei Huang } while (!DFH_EOL(header)); 15727d63899aSWei Huang 15737d63899aSWei Huang return -ENOENT; 15747d63899aSWei Huang } 15757d63899aSWei Huang 15767d63899aSWei Huang static int nlb_afu_ctx_release(struct afu_rawdev *dev) 15777d63899aSWei Huang { 15787d63899aSWei Huang struct n3000_afu_priv *priv = NULL; 15797d63899aSWei Huang struct nlb_afu_ctx *ctx = NULL; 15807d63899aSWei Huang 15817d63899aSWei Huang if (!dev) 15827d63899aSWei Huang return -EINVAL; 15837d63899aSWei Huang 15847d63899aSWei Huang priv = (struct n3000_afu_priv *)dev->priv; 15857d63899aSWei Huang if (!priv) 15867d63899aSWei Huang return -ENOENT; 15877d63899aSWei Huang 15887d63899aSWei Huang ctx = &priv->nlb_ctx; 15897d63899aSWei Huang 15907d63899aSWei Huang rte_free(ctx->dsm_ptr); 15917d63899aSWei Huang ctx->dsm_ptr = NULL; 15927d63899aSWei Huang ctx->status_ptr = NULL; 15937d63899aSWei Huang 15947d63899aSWei Huang rte_free(ctx->src_ptr); 15957d63899aSWei Huang ctx->src_ptr = NULL; 15967d63899aSWei Huang 15977d63899aSWei Huang rte_free(ctx->dest_ptr); 15987d63899aSWei Huang ctx->dest_ptr = NULL; 15997d63899aSWei Huang 16007d63899aSWei Huang return 0; 16017d63899aSWei Huang } 16027d63899aSWei Huang 16037d63899aSWei Huang static int nlb_afu_ctx_init(struct afu_rawdev *dev, uint8_t *addr) 16047d63899aSWei Huang { 16057d63899aSWei Huang struct n3000_afu_priv *priv = NULL; 16067d63899aSWei Huang struct nlb_afu_ctx *ctx = NULL; 16077d63899aSWei Huang int ret = 0; 16087d63899aSWei Huang 16097d63899aSWei Huang if (!dev || !addr) 16107d63899aSWei Huang return -EINVAL; 16117d63899aSWei Huang 16127d63899aSWei Huang priv = (struct n3000_afu_priv *)dev->priv; 16137d63899aSWei Huang if (!priv) 16147d63899aSWei Huang return -ENOENT; 16157d63899aSWei Huang 16167d63899aSWei Huang ctx = &priv->nlb_ctx; 16177d63899aSWei Huang ctx->addr = addr; 16187d63899aSWei Huang 16197d63899aSWei Huang ctx->dsm_ptr = (uint8_t *)rte_zmalloc(NULL, DSM_SIZE, TEST_MEM_ALIGN); 16207d63899aSWei Huang if (!ctx->dsm_ptr) 16217d63899aSWei Huang return -ENOMEM; 16227d63899aSWei Huang 16237d63899aSWei Huang ctx->dsm_iova = rte_malloc_virt2iova(ctx->dsm_ptr); 16247d63899aSWei Huang if (ctx->dsm_iova == RTE_BAD_IOVA) { 16257d63899aSWei Huang ret = -ENOMEM; 16267d63899aSWei Huang goto release_dsm; 16277d63899aSWei Huang } 16287d63899aSWei Huang 16297d63899aSWei Huang ctx->src_ptr = (uint8_t *)rte_zmalloc(NULL, NLB_BUF_SIZE, 16307d63899aSWei Huang TEST_MEM_ALIGN); 16317d63899aSWei Huang if (!ctx->src_ptr) { 16327d63899aSWei Huang ret = -ENOMEM; 16337d63899aSWei Huang goto release_dsm; 16347d63899aSWei Huang } 16357d63899aSWei Huang ctx->src_iova = rte_malloc_virt2iova(ctx->src_ptr); 16367d63899aSWei Huang if (ctx->src_iova == RTE_BAD_IOVA) { 16377d63899aSWei Huang ret = -ENOMEM; 16387d63899aSWei Huang goto release_src; 16397d63899aSWei Huang } 16407d63899aSWei Huang 16417d63899aSWei Huang ctx->dest_ptr = (uint8_t *)rte_zmalloc(NULL, NLB_BUF_SIZE, 16427d63899aSWei Huang TEST_MEM_ALIGN); 16437d63899aSWei Huang if (!ctx->dest_ptr) { 16447d63899aSWei Huang ret = -ENOMEM; 16457d63899aSWei Huang goto release_src; 16467d63899aSWei Huang } 16477d63899aSWei Huang ctx->dest_iova = rte_malloc_virt2iova(ctx->dest_ptr); 16487d63899aSWei Huang if (ctx->dest_iova == RTE_BAD_IOVA) { 16497d63899aSWei Huang ret = -ENOMEM; 16507d63899aSWei Huang goto release_dest; 16517d63899aSWei Huang } 16527d63899aSWei Huang 16537d63899aSWei Huang ctx->status_ptr = (struct nlb_dsm_status *)(ctx->dsm_ptr + DSM_STATUS); 16547d63899aSWei Huang return 0; 16557d63899aSWei Huang 16567d63899aSWei Huang release_dest: 16577d63899aSWei Huang rte_free(ctx->dest_ptr); 16587d63899aSWei Huang ctx->dest_ptr = NULL; 16597d63899aSWei Huang release_src: 16607d63899aSWei Huang rte_free(ctx->src_ptr); 16617d63899aSWei Huang ctx->src_ptr = NULL; 16627d63899aSWei Huang release_dsm: 16637d63899aSWei Huang rte_free(ctx->dsm_ptr); 16647d63899aSWei Huang ctx->dsm_ptr = NULL; 16657d63899aSWei Huang return ret; 16667d63899aSWei Huang } 16677d63899aSWei Huang 16687d63899aSWei Huang static int dma_afu_ctx_release(struct afu_rawdev *dev) 16697d63899aSWei Huang { 16707d63899aSWei Huang struct n3000_afu_priv *priv = NULL; 16717d63899aSWei Huang struct dma_afu_ctx *ctx = NULL; 16727d63899aSWei Huang 16737d63899aSWei Huang if (!dev) 16747d63899aSWei Huang return -EINVAL; 16757d63899aSWei Huang 16767d63899aSWei Huang priv = (struct n3000_afu_priv *)dev->priv; 16777d63899aSWei Huang if (!priv) 16787d63899aSWei Huang return -ENOENT; 16797d63899aSWei Huang 16807d63899aSWei Huang ctx = &priv->dma_ctx[0]; 16817d63899aSWei Huang 16827d63899aSWei Huang rte_free(ctx->desc_buf); 16837d63899aSWei Huang ctx->desc_buf = NULL; 16847d63899aSWei Huang 16857d63899aSWei Huang rte_free(ctx->magic_buf); 16867d63899aSWei Huang ctx->magic_buf = NULL; 16877d63899aSWei Huang 16887d63899aSWei Huang close(ctx->event_fd); 16897d63899aSWei Huang return 0; 16907d63899aSWei Huang } 16917d63899aSWei Huang 16927d63899aSWei Huang static int dma_afu_ctx_init(struct afu_rawdev *dev, int index, uint8_t *addr) 16937d63899aSWei Huang { 16947d63899aSWei Huang struct n3000_afu_priv *priv = NULL; 16957d63899aSWei Huang struct dma_afu_ctx *ctx = NULL; 16967d63899aSWei Huang uint64_t mem_sz[] = {0x100000000, 0x100000000, 0x40000000, 0x1000000}; 16977d63899aSWei Huang static int efds[1] = {0}; 16987d63899aSWei Huang uint32_t vec_start = 0; 16997d63899aSWei Huang int ret = 0; 17007d63899aSWei Huang 17017d63899aSWei Huang if (!dev || (index < 0) || (index >= NUM_N3000_DMA) || !addr) 17027d63899aSWei Huang return -EINVAL; 17037d63899aSWei Huang 17047d63899aSWei Huang priv = (struct n3000_afu_priv *)dev->priv; 17057d63899aSWei Huang if (!priv) 17067d63899aSWei Huang return -ENOENT; 17077d63899aSWei Huang 17087d63899aSWei Huang ctx = &priv->dma_ctx[index]; 17097d63899aSWei Huang ctx->index = index; 17107d63899aSWei Huang ctx->addr = addr; 17117d63899aSWei Huang ctx->csr_addr = addr + DMA_CSR; 17127d63899aSWei Huang ctx->desc_addr = addr + DMA_DESC; 17137d63899aSWei Huang ctx->ase_ctrl_addr = addr + DMA_ASE_CTRL; 17147d63899aSWei Huang ctx->ase_data_addr = addr + DMA_ASE_DATA; 17157d63899aSWei Huang ctx->mem_size = mem_sz[ctx->index]; 17167d63899aSWei Huang ctx->cur_ase_page = INVALID_ASE_PAGE; 17177d63899aSWei Huang if (ctx->index == 0) { 17187d63899aSWei Huang ret = n3000_afu_get_irq_capability(dev, &vec_start, NULL); 17197d63899aSWei Huang if (ret) 17207d63899aSWei Huang return ret; 17217d63899aSWei Huang 17227d63899aSWei Huang efds[0] = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); 17237d63899aSWei Huang if (efds[0] < 0) { 17247d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("eventfd create failed"); 17257d63899aSWei Huang return -EBADF; 17267d63899aSWei Huang } 17277d63899aSWei Huang #ifdef VFIO_PRESENT 17287d63899aSWei Huang if (dma_afu_set_irqs(dev, vec_start, 1, efds)) 17297d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("DMA interrupt setup failed"); 17307d63899aSWei Huang #endif 17317d63899aSWei Huang } 17327d63899aSWei Huang ctx->event_fd = efds[0]; 17337d63899aSWei Huang 17347d63899aSWei Huang ctx->desc_buf = (msgdma_ext_desc *)rte_zmalloc(NULL, 17357d63899aSWei Huang sizeof(msgdma_ext_desc), DMA_ALIGN_BYTES); 17367d63899aSWei Huang if (!ctx->desc_buf) { 17377d63899aSWei Huang ret = -ENOMEM; 17387d63899aSWei Huang goto release; 17397d63899aSWei Huang } 17407d63899aSWei Huang 17417d63899aSWei Huang ctx->magic_buf = (uint64_t *)rte_zmalloc(NULL, MAGIC_BUF_SIZE, 17427d63899aSWei Huang TEST_MEM_ALIGN); 17437d63899aSWei Huang if (!ctx->magic_buf) { 17447d63899aSWei Huang ret = -ENOMEM; 17457d63899aSWei Huang goto release; 17467d63899aSWei Huang } 17477d63899aSWei Huang ctx->magic_iova = rte_malloc_virt2iova(ctx->magic_buf); 17487d63899aSWei Huang if (ctx->magic_iova == RTE_BAD_IOVA) { 17497d63899aSWei Huang ret = -ENOMEM; 17507d63899aSWei Huang goto release; 17517d63899aSWei Huang } 17527d63899aSWei Huang 17537d63899aSWei Huang return 0; 17547d63899aSWei Huang 17557d63899aSWei Huang release: 17567d63899aSWei Huang dma_afu_ctx_release(dev); 17577d63899aSWei Huang return ret; 17587d63899aSWei Huang } 17597d63899aSWei Huang 17607d63899aSWei Huang static int n3000_afu_ctx_init(struct afu_rawdev *dev) 17617d63899aSWei Huang { 17627d63899aSWei Huang struct n3000_afu_priv *priv = NULL; 17637d63899aSWei Huang uint8_t *addr = NULL; 17647d63899aSWei Huang uint64_t header = 0; 17657d63899aSWei Huang uint64_t uuid_hi = 0; 17667d63899aSWei Huang uint64_t uuid_lo = 0; 17677d63899aSWei Huang uint64_t next_offset = 0; 17687d63899aSWei Huang int ret = 0; 17697d63899aSWei Huang 17707d63899aSWei Huang if (!dev) 17717d63899aSWei Huang return -EINVAL; 17727d63899aSWei Huang 17737d63899aSWei Huang priv = (struct n3000_afu_priv *)dev->priv; 17747d63899aSWei Huang if (!priv) 17757d63899aSWei Huang return -ENOENT; 17767d63899aSWei Huang 17777d63899aSWei Huang addr = (uint8_t *)dev->addr; 17787d63899aSWei Huang do { 17797d63899aSWei Huang addr += next_offset; 17807d63899aSWei Huang header = rte_read64(addr); 17817d63899aSWei Huang uuid_lo = rte_read64(addr + DFH_UUID_L_OFFSET); 17827d63899aSWei Huang uuid_hi = rte_read64(addr + DFH_UUID_H_OFFSET); 17837d63899aSWei Huang 17847d63899aSWei Huang if ((DFH_TYPE(header) == DFH_TYPE_AFU) && 17857d63899aSWei Huang (uuid_lo == N3000_NLB0_UUID_L) && 17867d63899aSWei Huang (uuid_hi == N3000_NLB0_UUID_H)) { 17877d63899aSWei Huang IFPGA_RAWDEV_PMD_INFO("AFU NLB0 found @ %p", (void *)addr); 17887d63899aSWei Huang ret = nlb_afu_ctx_init(dev, addr); 17897d63899aSWei Huang if (ret) 17907d63899aSWei Huang return ret; 17917d63899aSWei Huang } else if ((DFH_TYPE(header) == DFH_TYPE_BBB) && 17927d63899aSWei Huang (uuid_lo == N3000_DMA_UUID_L) && 17937d63899aSWei Huang (uuid_hi == N3000_DMA_UUID_H) && 17947d63899aSWei Huang (priv->num_dma < NUM_N3000_DMA)) { 17957d63899aSWei Huang IFPGA_RAWDEV_PMD_INFO("AFU DMA%d found @ %p", 17967d63899aSWei Huang priv->num_dma, (void *)addr); 17977d63899aSWei Huang ret = dma_afu_ctx_init(dev, priv->num_dma, addr); 17987d63899aSWei Huang if (ret) 17997d63899aSWei Huang return ret; 18007d63899aSWei Huang priv->num_dma++; 18017d63899aSWei Huang } else { 18027d63899aSWei Huang IFPGA_RAWDEV_PMD_DEBUG("DFH: type %"PRIu64 18037d63899aSWei Huang ", uuid %016"PRIx64"%016"PRIx64, 18047d63899aSWei Huang DFH_TYPE(header), uuid_hi, uuid_lo); 18057d63899aSWei Huang } 18067d63899aSWei Huang 18077d63899aSWei Huang next_offset = DFH_NEXT_OFFSET(header); 18087d63899aSWei Huang if (((next_offset & 0xffff) == 0xffff) || (next_offset == 0)) 18097d63899aSWei Huang break; 18107d63899aSWei Huang } while (!DFH_EOL(header)); 18117d63899aSWei Huang 18127d63899aSWei Huang return 0; 18137d63899aSWei Huang } 18147d63899aSWei Huang 18157d63899aSWei Huang static int n3000_afu_init(struct afu_rawdev *dev) 18167d63899aSWei Huang { 18177d63899aSWei Huang if (!dev) 18187d63899aSWei Huang return -EINVAL; 18197d63899aSWei Huang 18207d63899aSWei Huang if (!dev->priv) { 18217d63899aSWei Huang dev->priv = rte_zmalloc(NULL, sizeof(struct n3000_afu_priv), 0); 18227d63899aSWei Huang if (!dev->priv) 18237d63899aSWei Huang return -ENOMEM; 18247d63899aSWei Huang } 18257d63899aSWei Huang 18267d63899aSWei Huang return n3000_afu_ctx_init(dev); 18277d63899aSWei Huang } 18287d63899aSWei Huang 18297d63899aSWei Huang static int n3000_afu_config(struct afu_rawdev *dev, void *config, 18307d63899aSWei Huang size_t config_size) 18317d63899aSWei Huang { 18327d63899aSWei Huang struct n3000_afu_priv *priv = NULL; 18337d63899aSWei Huang struct rte_pmd_afu_n3000_cfg *cfg = NULL; 18347d63899aSWei Huang int i = 0; 18357d63899aSWei Huang uint64_t top = 0; 18367d63899aSWei Huang 18377d63899aSWei Huang if (!dev || !config || !config_size) 18387d63899aSWei Huang return -EINVAL; 18397d63899aSWei Huang 18407d63899aSWei Huang priv = (struct n3000_afu_priv *)dev->priv; 18417d63899aSWei Huang if (!priv) 18427d63899aSWei Huang return -ENOENT; 18437d63899aSWei Huang 18447d63899aSWei Huang if (config_size != sizeof(struct rte_pmd_afu_n3000_cfg)) 18457d63899aSWei Huang return -EINVAL; 18467d63899aSWei Huang 18477d63899aSWei Huang cfg = (struct rte_pmd_afu_n3000_cfg *)config; 18487d63899aSWei Huang if (cfg->type == RTE_PMD_AFU_N3000_NLB) { 18497d63899aSWei Huang if (cfg->nlb_cfg.mode != NLB_MODE_LPBK) 18507d63899aSWei Huang return -EINVAL; 18517d63899aSWei Huang if ((cfg->nlb_cfg.read_vc > NLB_VC_RANDOM) || 18527d63899aSWei Huang (cfg->nlb_cfg.write_vc > NLB_VC_RANDOM)) 18537d63899aSWei Huang return -EINVAL; 18547d63899aSWei Huang if (cfg->nlb_cfg.wrfence_vc > NLB_VC_VH1) 18557d63899aSWei Huang return -EINVAL; 18567d63899aSWei Huang if (cfg->nlb_cfg.cache_hint > NLB_RDLINE_MIXED) 18577d63899aSWei Huang return -EINVAL; 18587d63899aSWei Huang if (cfg->nlb_cfg.cache_policy > NLB_WRPUSH_I) 18597d63899aSWei Huang return -EINVAL; 18607d63899aSWei Huang if ((cfg->nlb_cfg.multi_cl != 1) && 18617d63899aSWei Huang (cfg->nlb_cfg.multi_cl != 2) && 18627d63899aSWei Huang (cfg->nlb_cfg.multi_cl != 4)) 18637d63899aSWei Huang return -EINVAL; 18647d63899aSWei Huang if ((cfg->nlb_cfg.begin < MIN_CACHE_LINES) || 18657d63899aSWei Huang (cfg->nlb_cfg.begin > MAX_CACHE_LINES)) 18667d63899aSWei Huang return -EINVAL; 18677d63899aSWei Huang if ((cfg->nlb_cfg.end < cfg->nlb_cfg.begin) || 18687d63899aSWei Huang (cfg->nlb_cfg.end > MAX_CACHE_LINES)) 18697d63899aSWei Huang return -EINVAL; 18707d63899aSWei Huang rte_memcpy(&priv->nlb_cfg, &cfg->nlb_cfg, 18717d63899aSWei Huang sizeof(struct rte_pmd_afu_nlb_cfg)); 18727d63899aSWei Huang } else if (cfg->type == RTE_PMD_AFU_N3000_DMA) { 18737d63899aSWei Huang if (cfg->dma_cfg.index >= NUM_N3000_DMA) 18747d63899aSWei Huang return -EINVAL; 18757d63899aSWei Huang i = cfg->dma_cfg.index; 18767d63899aSWei Huang if (cfg->dma_cfg.length > priv->dma_ctx[i].mem_size) 18777d63899aSWei Huang return -EINVAL; 18787d63899aSWei Huang if (cfg->dma_cfg.offset >= priv->dma_ctx[i].mem_size) 18797d63899aSWei Huang return -EINVAL; 18807d63899aSWei Huang top = cfg->dma_cfg.length + cfg->dma_cfg.offset; 18817d63899aSWei Huang if ((top == 0) || (top > priv->dma_ctx[i].mem_size)) 18827d63899aSWei Huang return -EINVAL; 18837d63899aSWei Huang if (i == 3) { /* QDR connected to DMA3 */ 18847d63899aSWei Huang if (cfg->dma_cfg.length & 0x3f) { 18857d63899aSWei Huang cfg->dma_cfg.length &= ~0x3f; 18867d63899aSWei Huang IFPGA_RAWDEV_PMD_INFO("Round size to %x for QDR", 18877d63899aSWei Huang cfg->dma_cfg.length); 18887d63899aSWei Huang } 18897d63899aSWei Huang } 18907d63899aSWei Huang rte_memcpy(&priv->dma_cfg, &cfg->dma_cfg, 18917d63899aSWei Huang sizeof(struct rte_pmd_afu_dma_cfg)); 18927d63899aSWei Huang } else { 18937d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Invalid type of N3000 AFU"); 18947d63899aSWei Huang return -EINVAL; 18957d63899aSWei Huang } 18967d63899aSWei Huang 18977d63899aSWei Huang priv->cfg_type = cfg->type; 18987d63899aSWei Huang return 0; 18997d63899aSWei Huang } 19007d63899aSWei Huang 19017d63899aSWei Huang static int n3000_afu_test(struct afu_rawdev *dev) 19027d63899aSWei Huang { 19037d63899aSWei Huang struct n3000_afu_priv *priv = NULL; 19047d63899aSWei Huang int ret = 0; 19057d63899aSWei Huang 19067d63899aSWei Huang if (!dev) 19077d63899aSWei Huang return -EINVAL; 19087d63899aSWei Huang 19097d63899aSWei Huang if (!dev->priv) 19107d63899aSWei Huang return -ENOENT; 19117d63899aSWei Huang 19127d63899aSWei Huang priv = (struct n3000_afu_priv *)dev->priv; 19137d63899aSWei Huang 19147d63899aSWei Huang if (priv->cfg_type == RTE_PMD_AFU_N3000_NLB) { 19157d63899aSWei Huang IFPGA_RAWDEV_PMD_INFO("Test NLB"); 19167d63899aSWei Huang ret = nlb_afu_test(dev); 19177d63899aSWei Huang } else if (priv->cfg_type == RTE_PMD_AFU_N3000_DMA) { 19187d63899aSWei Huang IFPGA_RAWDEV_PMD_INFO("Test DMA%u", priv->dma_cfg.index); 19197d63899aSWei Huang ret = dma_afu_test(dev); 19207d63899aSWei Huang } else { 19217d63899aSWei Huang IFPGA_RAWDEV_PMD_ERR("Please configure AFU before test"); 19227d63899aSWei Huang ret = -EINVAL; 19237d63899aSWei Huang } 19247d63899aSWei Huang 19257d63899aSWei Huang return ret; 19267d63899aSWei Huang } 19277d63899aSWei Huang 19287d63899aSWei Huang static int n3000_afu_close(struct afu_rawdev *dev) 19297d63899aSWei Huang { 19307d63899aSWei Huang if (!dev) 19317d63899aSWei Huang return -EINVAL; 19327d63899aSWei Huang 19337d63899aSWei Huang nlb_afu_ctx_release(dev); 19347d63899aSWei Huang dma_afu_ctx_release(dev); 19357d63899aSWei Huang 19367d63899aSWei Huang rte_free(dev->priv); 19377d63899aSWei Huang dev->priv = NULL; 19387d63899aSWei Huang 19397d63899aSWei Huang return 0; 19407d63899aSWei Huang } 19417d63899aSWei Huang 19427d63899aSWei Huang static int n3000_afu_dump(struct afu_rawdev *dev, FILE *f) 19437d63899aSWei Huang { 19447d63899aSWei Huang struct n3000_afu_priv *priv = NULL; 19457d63899aSWei Huang 19467d63899aSWei Huang if (!dev) 19477d63899aSWei Huang return -EINVAL; 19487d63899aSWei Huang 19497d63899aSWei Huang priv = (struct n3000_afu_priv *)dev->priv; 19507d63899aSWei Huang if (!priv) 19517d63899aSWei Huang return -ENOENT; 19527d63899aSWei Huang 19537d63899aSWei Huang if (!f) 19547d63899aSWei Huang f = stdout; 19557d63899aSWei Huang 19567d63899aSWei Huang if (priv->cfg_type == RTE_PMD_AFU_N3000_NLB) { 19577d63899aSWei Huang struct nlb_afu_ctx *ctx = &priv->nlb_ctx; 19587d63899aSWei Huang fprintf(f, "addr:\t\t%p\n", (void *)ctx->addr); 19597d63899aSWei Huang fprintf(f, "dsm_ptr:\t%p\n", (void *)ctx->dsm_ptr); 19607d63899aSWei Huang fprintf(f, "dsm_iova:\t0x%"PRIx64"\n", ctx->dsm_iova); 19617d63899aSWei Huang fprintf(f, "src_ptr:\t%p\n", (void *)ctx->src_ptr); 19627d63899aSWei Huang fprintf(f, "src_iova:\t0x%"PRIx64"\n", ctx->src_iova); 19637d63899aSWei Huang fprintf(f, "dest_ptr:\t%p\n", (void *)ctx->dest_ptr); 19647d63899aSWei Huang fprintf(f, "dest_iova:\t0x%"PRIx64"\n", ctx->dest_iova); 19657d63899aSWei Huang fprintf(f, "status_ptr:\t%p\n", (void *)ctx->status_ptr); 19667d63899aSWei Huang } else if (priv->cfg_type == RTE_PMD_AFU_N3000_DMA) { 19677d63899aSWei Huang struct dma_afu_ctx *ctx = &priv->dma_ctx[priv->dma_cfg.index]; 19687d63899aSWei Huang fprintf(f, "index:\t\t%d\n", ctx->index); 19697d63899aSWei Huang fprintf(f, "addr:\t\t%p\n", (void *)ctx->addr); 19707d63899aSWei Huang fprintf(f, "csr_addr:\t%p\n", (void *)ctx->csr_addr); 19717d63899aSWei Huang fprintf(f, "desc_addr:\t%p\n", (void *)ctx->desc_addr); 19727d63899aSWei Huang fprintf(f, "ase_ctrl_addr:\t%p\n", (void *)ctx->ase_ctrl_addr); 19737d63899aSWei Huang fprintf(f, "ase_data_addr:\t%p\n", (void *)ctx->ase_data_addr); 19747d63899aSWei Huang fprintf(f, "desc_buf:\t%p\n", (void *)ctx->desc_buf); 19757d63899aSWei Huang fprintf(f, "magic_buf:\t%p\n", (void *)ctx->magic_buf); 19767d63899aSWei Huang fprintf(f, "magic_iova:\t0x%"PRIx64"\n", ctx->magic_iova); 19777d63899aSWei Huang } else { 19787d63899aSWei Huang return -EINVAL; 19797d63899aSWei Huang } 19807d63899aSWei Huang 19817d63899aSWei Huang return 0; 19827d63899aSWei Huang } 19837d63899aSWei Huang 19847d63899aSWei Huang static int n3000_afu_reset(struct afu_rawdev *dev) 19857d63899aSWei Huang { 19867d63899aSWei Huang uint8_t *addr = NULL; 19877d63899aSWei Huang uint64_t val = 0; 19887d63899aSWei Huang 19897d63899aSWei Huang addr = (uint8_t *)n3000_afu_get_port_addr(dev); 19907d63899aSWei Huang if (!addr) 19917d63899aSWei Huang return -ENOENT; 19927d63899aSWei Huang 19937d63899aSWei Huang val = rte_read64(addr + PORT_CTRL_REG); 19947d63899aSWei Huang val |= PORT_SOFT_RESET; 19957d63899aSWei Huang rte_write64(val, addr + PORT_CTRL_REG); 19967d63899aSWei Huang rte_delay_us(100); 19977d63899aSWei Huang val &= ~PORT_SOFT_RESET; 19987d63899aSWei Huang rte_write64(val, addr + PORT_CTRL_REG); 19997d63899aSWei Huang 20007d63899aSWei Huang return 0; 20017d63899aSWei Huang } 20027d63899aSWei Huang 20037d63899aSWei Huang static struct afu_ops n3000_afu_ops = { 20047d63899aSWei Huang .init = n3000_afu_init, 20057d63899aSWei Huang .config = n3000_afu_config, 20067d63899aSWei Huang .start = NULL, 20077d63899aSWei Huang .stop = NULL, 20087d63899aSWei Huang .test = n3000_afu_test, 20097d63899aSWei Huang .close = n3000_afu_close, 20107d63899aSWei Huang .dump = n3000_afu_dump, 20117d63899aSWei Huang .reset = n3000_afu_reset 20127d63899aSWei Huang }; 20137d63899aSWei Huang 20147d63899aSWei Huang static struct afu_rawdev_drv n3000_afu_drv = { 20157d63899aSWei Huang .uuid = { N3000_AFU_UUID_L, N3000_AFU_UUID_H }, 20167d63899aSWei Huang .ops = &n3000_afu_ops 20177d63899aSWei Huang }; 20187d63899aSWei Huang 20197d63899aSWei Huang AFU_PMD_REGISTER(n3000_afu_drv); 2020