1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2022 Intel Corporation
13 #include <sys/eventfd.h>
14 #include <sys/ioctl.h>
17 #include <rte_malloc.h>
18 #include <rte_memcpy.h>
21 #include <rte_bus_pci.h>
22 #include <rte_bus_ifpga.h>
23 #include <rte_rawdev.h>
25 #include "afu_pmd_core.h"
26 #include "afu_pmd_he_hssi.h"
28 static int he_hssi_indirect_write(struct he_hssi_ctx *ctx, uint32_t addr,
31 struct traffic_ctrl_cmd cmd;
32 struct traffic_ctrl_data data;
35 IFPGA_RAWDEV_PMD_DEBUG("Indirect write 0x%x, value 0x%08x", addr, value);
40 data.write_data = value;
41 rte_write64(data.csr, ctx->addr + TRAFFIC_CTRL_DATA);
45 cmd.afu_cmd_addr = addr;
46 rte_write64(cmd.csr, ctx->addr + TRAFFIC_CTRL_CMD);
48 while (i < MAILBOX_TIMEOUT_MS) {
49 rte_delay_ms(MAILBOX_POLL_INTERVAL_MS);
50 cmd.csr = rte_read64(ctx->addr + TRAFFIC_CTRL_CMD);
53 i += MAILBOX_POLL_INTERVAL_MS;
55 if (i >= MAILBOX_TIMEOUT_MS)
60 while (i < MAILBOX_TIMEOUT_MS) {
62 rte_write64(cmd.csr, ctx->addr + TRAFFIC_CTRL_CMD);
63 rte_delay_ms(MAILBOX_POLL_INTERVAL_MS);
64 cmd.csr = rte_read64(ctx->addr + TRAFFIC_CTRL_CMD);
67 i += MAILBOX_POLL_INTERVAL_MS;
69 if (i >= MAILBOX_TIMEOUT_MS)
75 static int he_hssi_indirect_read(struct he_hssi_ctx *ctx, uint32_t addr,
78 struct traffic_ctrl_cmd cmd;
79 struct traffic_ctrl_data data;
87 cmd.afu_cmd_addr = addr;
88 rte_write64(cmd.csr, ctx->addr + TRAFFIC_CTRL_CMD);
90 while (i < MAILBOX_TIMEOUT_MS) {
91 rte_delay_ms(MAILBOX_POLL_INTERVAL_MS);
92 cmd.csr = rte_read64(ctx->addr + TRAFFIC_CTRL_CMD);
94 data.csr = rte_read64(ctx->addr + TRAFFIC_CTRL_DATA);
95 *value = data.read_data;
98 i += MAILBOX_POLL_INTERVAL_MS;
100 if (i >= MAILBOX_TIMEOUT_MS)
105 while (i < MAILBOX_TIMEOUT_MS) {
107 rte_write64(cmd.csr, ctx->addr + TRAFFIC_CTRL_CMD);
108 rte_delay_ms(MAILBOX_POLL_INTERVAL_MS);
109 cmd.csr = rte_read64(ctx->addr + TRAFFIC_CTRL_CMD);
112 i += MAILBOX_POLL_INTERVAL_MS;
114 if (i >= MAILBOX_TIMEOUT_MS)
117 IFPGA_RAWDEV_PMD_DEBUG("Indirect read 0x%x, value 0x%08x", addr, *value);
121 static void he_hssi_report(struct he_hssi_ctx *ctx)
127 ret = he_hssi_indirect_read(ctx, TM_PKT_GOOD, &val);
130 printf("Number of good packets received: %u\n", val);
132 ret = he_hssi_indirect_read(ctx, TM_PKT_BAD, &val);
135 printf("Number of bad packets received: %u\n", val);
137 ret = he_hssi_indirect_read(ctx, TM_BYTE_CNT1, &val);
141 ret = he_hssi_indirect_read(ctx, TM_BYTE_CNT0, &val);
144 v64 = (v64 << 32) | val;
145 printf("Number of bytes received: %"PRIu64"\n", v64);
147 ret = he_hssi_indirect_read(ctx, TM_AVST_RX_ERR, &val);
150 if (val & ERR_VALID) {
151 printf("AVST rx error:");
152 if (val & OVERFLOW_ERR)
154 if (val & LENGTH_ERR)
156 if (val & OVERSIZE_ERR)
158 if (val & UNDERSIZE_ERR)
159 printf(" undersize");
160 if (val & MAC_CRC_ERR)
167 ret = he_hssi_indirect_read(ctx, LOOPBACK_FIFO_STATUS, &val);
170 if (val & (ALMOST_EMPTY | ALMOST_FULL)) {
171 printf("FIFO status:");
172 if (val & ALMOST_EMPTY)
173 printf(" almost empty");
174 if (val & ALMOST_FULL)
175 printf(" almost full");
180 static int he_hssi_test(struct afu_rawdev *dev)
182 struct he_hssi_priv *priv = NULL;
183 struct rte_pmd_afu_he_hssi_cfg *cfg = NULL;
184 struct he_hssi_ctx *ctx = NULL;
185 struct traffic_ctrl_ch_sel sel;
193 priv = (struct he_hssi_priv *)dev->priv;
197 cfg = &priv->he_hssi_cfg;
198 ctx = &priv->he_hssi_ctx;
200 ret = he_hssi_indirect_write(ctx, TG_STOP_XFR, 0);
204 sel.channel_sel = cfg->port;
205 rte_write64(sel.csr, ctx->addr + TRAFFIC_CTRL_CH_SEL);
207 if (cfg->he_loopback >= 0) {
208 val = cfg->he_loopback ? 1 : 0;
209 IFPGA_RAWDEV_PMD_INFO("%s HE loopback on port %u",
210 val ? "Enable" : "Disable", cfg->port);
211 return he_hssi_indirect_write(ctx, LOOPBACK_EN, val);
214 ret = he_hssi_indirect_write(ctx, TG_NUM_PKT, cfg->num_packets);
218 ret = he_hssi_indirect_write(ctx, TG_PKT_LEN, cfg->packet_length);
222 val = cfg->src_addr & 0xffffffff;
223 ret = he_hssi_indirect_write(ctx, TG_SRC_MAC_L, val);
226 val = (cfg->src_addr >> 32) & 0xffff;
227 ret = he_hssi_indirect_write(ctx, TG_SRC_MAC_H, val);
231 val = cfg->dest_addr & 0xffffffff;
232 ret = he_hssi_indirect_write(ctx, TG_DST_MAC_L, val);
235 val = (cfg->dest_addr >> 32) & 0xffff;
236 ret = he_hssi_indirect_write(ctx, TG_DST_MAC_H, val);
240 val = cfg->random_length ? 1 : 0;
241 ret = he_hssi_indirect_write(ctx, TG_PKT_LEN_TYPE, val);
245 val = cfg->random_payload ? 1 : 0;
246 ret = he_hssi_indirect_write(ctx, TG_DATA_PATTERN, val);
250 for (i = 0; i < TG_NUM_RND_SEEDS; i++) {
251 ret = he_hssi_indirect_write(ctx, TG_RANDOM_SEED(i),
257 ret = he_hssi_indirect_write(ctx, TG_START_XFR, 1);
261 while (i++ < cfg->timeout) {
262 ret = he_hssi_indirect_read(ctx, TG_PKT_XFRD, &val);
265 if (val == cfg->num_packets)
275 static int he_hssi_init(struct afu_rawdev *dev)
277 struct he_hssi_priv *priv = NULL;
278 struct he_hssi_ctx *ctx = NULL;
283 priv = (struct he_hssi_priv *)dev->priv;
285 priv = rte_zmalloc(NULL, sizeof(struct he_hssi_priv), 0);
291 ctx = &priv->he_hssi_ctx;
292 ctx->addr = (uint8_t *)dev->addr;
297 static int he_hssi_config(struct afu_rawdev *dev, void *config,
300 struct he_hssi_priv *priv = NULL;
301 struct rte_pmd_afu_he_hssi_cfg *cfg = NULL;
303 if (!dev || !config || !config_size)
306 priv = (struct he_hssi_priv *)dev->priv;
310 if (config_size != sizeof(struct rte_pmd_afu_he_hssi_cfg))
313 cfg = (struct rte_pmd_afu_he_hssi_cfg *)config;
314 if (cfg->port >= NUM_HE_HSSI_PORTS)
317 rte_memcpy(&priv->he_hssi_cfg, cfg, sizeof(priv->he_hssi_cfg));
322 static int he_hssi_close(struct afu_rawdev *dev)
333 static int he_hssi_dump(struct afu_rawdev *dev, FILE *f)
335 struct he_hssi_priv *priv = NULL;
336 struct he_hssi_ctx *ctx = NULL;
341 priv = (struct he_hssi_priv *)dev->priv;
348 ctx = &priv->he_hssi_ctx;
350 fprintf(f, "addr:\t\t%p\n", (void *)ctx->addr);
355 static struct afu_ops he_hssi_ops = {
356 .init = he_hssi_init,
357 .config = he_hssi_config,
360 .test = he_hssi_test,
361 .close = he_hssi_close,
362 .dump = he_hssi_dump,
366 struct afu_rawdev_drv he_hssi_drv = {
367 .uuid = { HE_HSSI_UUID_L, HE_HSSI_UUID_H },
371 AFU_PMD_REGISTER(he_hssi_drv);