xref: /dpdk/drivers/raw/ifpga/afu_pmd_he_mem.c (revision 1f37cb2bb46b1fd403faa7c3bf8884e6a4dfde66)
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