172dbdec4SWei Huang /* SPDX-License-Identifier: BSD-3-Clause
272dbdec4SWei Huang * Copyright(c) 2022 Intel Corporation
372dbdec4SWei Huang */
472dbdec4SWei Huang
572dbdec4SWei Huang #include <errno.h>
672dbdec4SWei Huang #include <stdio.h>
772dbdec4SWei Huang #include <stdint.h>
872dbdec4SWei Huang #include <stdlib.h>
972dbdec4SWei Huang #include <unistd.h>
1072dbdec4SWei Huang #include <fcntl.h>
1172dbdec4SWei Huang #include <poll.h>
1272dbdec4SWei Huang #include <sys/eventfd.h>
1372dbdec4SWei Huang #include <sys/ioctl.h>
1472dbdec4SWei Huang
1572dbdec4SWei Huang #include <rte_eal.h>
1672dbdec4SWei Huang #include <rte_malloc.h>
1772dbdec4SWei Huang #include <rte_memcpy.h>
1872dbdec4SWei Huang #include <rte_io.h>
1972dbdec4SWei Huang #include <rte_vfio.h>
20*1f37cb2bSDavid Marchand #include <bus_pci_driver.h>
21925c074eSDavid Marchand #include <bus_ifpga_driver.h>
2272dbdec4SWei Huang #include <rte_rawdev.h>
2372dbdec4SWei Huang
2472dbdec4SWei Huang #include "afu_pmd_core.h"
2572dbdec4SWei Huang #include "afu_pmd_he_mem.h"
2672dbdec4SWei Huang
he_mem_tg_test(struct afu_rawdev * dev)2772dbdec4SWei Huang static int he_mem_tg_test(struct afu_rawdev *dev)
2872dbdec4SWei Huang {
2972dbdec4SWei Huang struct he_mem_tg_priv *priv = NULL;
3072dbdec4SWei Huang struct rte_pmd_afu_he_mem_tg_cfg *cfg = NULL;
3172dbdec4SWei Huang struct he_mem_tg_ctx *ctx = NULL;
3272dbdec4SWei Huang uint64_t value = 0x12345678;
3372dbdec4SWei Huang uint64_t cap = 0;
3472dbdec4SWei Huang uint64_t channel_mask = 0;
3572dbdec4SWei Huang int i, t = 0;
3672dbdec4SWei Huang
3772dbdec4SWei Huang if (!dev)
3872dbdec4SWei Huang return -EINVAL;
3972dbdec4SWei Huang
4072dbdec4SWei Huang priv = (struct he_mem_tg_priv *)dev->priv;
4172dbdec4SWei Huang if (!priv)
4272dbdec4SWei Huang return -ENOENT;
4372dbdec4SWei Huang
4472dbdec4SWei Huang cfg = &priv->he_mem_tg_cfg;
4572dbdec4SWei Huang ctx = &priv->he_mem_tg_ctx;
4672dbdec4SWei Huang
4772dbdec4SWei Huang IFPGA_RAWDEV_PMD_DEBUG("Channel mask: 0x%x", cfg->channel_mask);
4872dbdec4SWei Huang
4972dbdec4SWei Huang rte_write64(value, ctx->addr + MEM_TG_SCRATCHPAD);
5072dbdec4SWei Huang cap = rte_read64(ctx->addr + MEM_TG_SCRATCHPAD);
5172dbdec4SWei Huang IFPGA_RAWDEV_PMD_DEBUG("Scratchpad value: 0x%"PRIx64, cap);
5272dbdec4SWei Huang if (cap != value) {
5372dbdec4SWei Huang IFPGA_RAWDEV_PMD_ERR("Test scratchpad register failed");
5472dbdec4SWei Huang return -EIO;
5572dbdec4SWei Huang }
5672dbdec4SWei Huang
5772dbdec4SWei Huang cap = rte_read64(ctx->addr + MEM_TG_CTRL);
5872dbdec4SWei Huang IFPGA_RAWDEV_PMD_DEBUG("Capability: 0x%"PRIx64, cap);
5972dbdec4SWei Huang
6072dbdec4SWei Huang channel_mask = cfg->channel_mask & cap;
6172dbdec4SWei Huang /* start traffic generators */
6272dbdec4SWei Huang rte_write64(channel_mask, ctx->addr + MEM_TG_CTRL);
6372dbdec4SWei Huang
6472dbdec4SWei Huang /* check test status */
6572dbdec4SWei Huang while (t < MEM_TG_TIMEOUT_MS) {
6672dbdec4SWei Huang value = rte_read64(ctx->addr + MEM_TG_STAT);
6772dbdec4SWei Huang for (i = 0; i < NUM_MEM_TG_CHANNELS; i++) {
6872dbdec4SWei Huang if (channel_mask & (1 << i)) {
6972dbdec4SWei Huang if (TGACTIVE(value, i))
7072dbdec4SWei Huang continue;
7172dbdec4SWei Huang printf("TG channel %d test %s\n", i,
7272dbdec4SWei Huang TGPASS(value, i) ? "pass" :
7372dbdec4SWei Huang TGTIMEOUT(value, i) ? "timeout" :
7472dbdec4SWei Huang TGFAIL(value, i) ? "fail" : "error");
7572dbdec4SWei Huang channel_mask &= ~(1 << i);
7672dbdec4SWei Huang }
7772dbdec4SWei Huang }
7872dbdec4SWei Huang if (!channel_mask)
7972dbdec4SWei Huang break;
8072dbdec4SWei Huang rte_delay_ms(MEM_TG_POLL_INTERVAL_MS);
8172dbdec4SWei Huang t += MEM_TG_POLL_INTERVAL_MS;
8272dbdec4SWei Huang }
8372dbdec4SWei Huang
8472dbdec4SWei Huang if (channel_mask) {
8572dbdec4SWei Huang IFPGA_RAWDEV_PMD_ERR("Timeout 0x%04lx", (unsigned long)value);
8672dbdec4SWei Huang return channel_mask;
8772dbdec4SWei Huang }
8872dbdec4SWei Huang
8972dbdec4SWei Huang return 0;
9072dbdec4SWei Huang }
9172dbdec4SWei Huang
he_mem_tg_init(struct afu_rawdev * dev)9272dbdec4SWei Huang static int he_mem_tg_init(struct afu_rawdev *dev)
9372dbdec4SWei Huang {
9472dbdec4SWei Huang struct he_mem_tg_priv *priv = NULL;
9572dbdec4SWei Huang struct he_mem_tg_ctx *ctx = NULL;
9672dbdec4SWei Huang
9772dbdec4SWei Huang if (!dev)
9872dbdec4SWei Huang return -EINVAL;
9972dbdec4SWei Huang
10072dbdec4SWei Huang priv = (struct he_mem_tg_priv *)dev->priv;
10172dbdec4SWei Huang if (!priv) {
10272dbdec4SWei Huang priv = rte_zmalloc(NULL, sizeof(struct he_mem_tg_priv), 0);
10372dbdec4SWei Huang if (!priv)
10472dbdec4SWei Huang return -ENOMEM;
10572dbdec4SWei Huang dev->priv = priv;
10672dbdec4SWei Huang }
10772dbdec4SWei Huang
10872dbdec4SWei Huang ctx = &priv->he_mem_tg_ctx;
10972dbdec4SWei Huang ctx->addr = (uint8_t *)dev->addr;
11072dbdec4SWei Huang
11172dbdec4SWei Huang return 0;
11272dbdec4SWei Huang }
11372dbdec4SWei Huang
he_mem_tg_config(struct afu_rawdev * dev,void * config,size_t config_size)11472dbdec4SWei Huang static int he_mem_tg_config(struct afu_rawdev *dev, void *config,
11572dbdec4SWei Huang size_t config_size)
11672dbdec4SWei Huang {
11772dbdec4SWei Huang struct he_mem_tg_priv *priv = NULL;
11872dbdec4SWei Huang
11972dbdec4SWei Huang if (!dev || !config || !config_size)
12072dbdec4SWei Huang return -EINVAL;
12172dbdec4SWei Huang
12272dbdec4SWei Huang priv = (struct he_mem_tg_priv *)dev->priv;
12372dbdec4SWei Huang if (!priv)
12472dbdec4SWei Huang return -ENOENT;
12572dbdec4SWei Huang
12672dbdec4SWei Huang if (config_size != sizeof(struct rte_pmd_afu_he_mem_tg_cfg))
12772dbdec4SWei Huang return -EINVAL;
12872dbdec4SWei Huang
12972dbdec4SWei Huang rte_memcpy(&priv->he_mem_tg_cfg, config, sizeof(priv->he_mem_tg_cfg));
13072dbdec4SWei Huang
13172dbdec4SWei Huang return 0;
13272dbdec4SWei Huang }
13372dbdec4SWei Huang
he_mem_tg_close(struct afu_rawdev * dev)13472dbdec4SWei Huang static int he_mem_tg_close(struct afu_rawdev *dev)
13572dbdec4SWei Huang {
13672dbdec4SWei Huang if (!dev)
13772dbdec4SWei Huang return -EINVAL;
13872dbdec4SWei Huang
13972dbdec4SWei Huang rte_free(dev->priv);
14072dbdec4SWei Huang dev->priv = NULL;
14172dbdec4SWei Huang
14272dbdec4SWei Huang return 0;
14372dbdec4SWei Huang }
14472dbdec4SWei Huang
he_mem_tg_dump(struct afu_rawdev * dev,FILE * f)14572dbdec4SWei Huang static int he_mem_tg_dump(struct afu_rawdev *dev, FILE *f)
14672dbdec4SWei Huang {
14772dbdec4SWei Huang struct he_mem_tg_priv *priv = NULL;
14872dbdec4SWei Huang struct he_mem_tg_ctx *ctx = NULL;
14972dbdec4SWei Huang
15072dbdec4SWei Huang if (!dev)
15172dbdec4SWei Huang return -EINVAL;
15272dbdec4SWei Huang
15372dbdec4SWei Huang priv = (struct he_mem_tg_priv *)dev->priv;
15472dbdec4SWei Huang if (!priv)
15572dbdec4SWei Huang return -ENOENT;
15672dbdec4SWei Huang
15772dbdec4SWei Huang if (!f)
15872dbdec4SWei Huang f = stdout;
15972dbdec4SWei Huang
16072dbdec4SWei Huang ctx = &priv->he_mem_tg_ctx;
16172dbdec4SWei Huang
16272dbdec4SWei Huang fprintf(f, "addr:\t\t%p\n", (void *)ctx->addr);
16372dbdec4SWei Huang
16472dbdec4SWei Huang return 0;
16572dbdec4SWei Huang }
16672dbdec4SWei Huang
16772dbdec4SWei Huang static struct afu_ops he_mem_tg_ops = {
16872dbdec4SWei Huang .init = he_mem_tg_init,
16972dbdec4SWei Huang .config = he_mem_tg_config,
17072dbdec4SWei Huang .start = NULL,
17172dbdec4SWei Huang .stop = NULL,
17272dbdec4SWei Huang .test = he_mem_tg_test,
17372dbdec4SWei Huang .close = he_mem_tg_close,
17472dbdec4SWei Huang .dump = he_mem_tg_dump,
17572dbdec4SWei Huang .reset = NULL
17672dbdec4SWei Huang };
17772dbdec4SWei Huang
17872dbdec4SWei Huang struct afu_rawdev_drv he_mem_tg_drv = {
17972dbdec4SWei Huang .uuid = { HE_MEM_TG_UUID_L, HE_MEM_TG_UUID_H },
18072dbdec4SWei Huang .ops = &he_mem_tg_ops
18172dbdec4SWei Huang };
18272dbdec4SWei Huang
18372dbdec4SWei Huang AFU_PMD_REGISTER(he_mem_tg_drv);
184