raw/cnxk_bphy: support CGX self test
authorTomasz Duszynski <tduszynski@marvell.com>
Mon, 21 Jun 2021 15:04:31 +0000 (17:04 +0200)
committerThomas Monjalon <thomas@monjalon.net>
Mon, 5 Jul 2021 21:07:32 +0000 (23:07 +0200)
Add support for performing selftest operation.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
Signed-off-by: Jakub Palider <jpalider@marvell.com>
Reviewed-by: Jerin Jacob <jerinj@marvell.com>
doc/guides/rawdevs/cnxk_bphy.rst
drivers/raw/cnxk_bphy/cnxk_bphy_cgx.c
drivers/raw/cnxk_bphy/cnxk_bphy_cgx.h [new file with mode: 0644]
drivers/raw/cnxk_bphy/cnxk_bphy_cgx_test.c [new file with mode: 0644]
drivers/raw/cnxk_bphy/meson.build

index 0d842a8..120f953 100644 (file)
@@ -38,7 +38,8 @@ To perform data transfer use standard ``rte_rawdev_enqueue_buffers()`` and
 responses hence dequeueing is not always necessary.
 
 BPHY CGX/RPM PMD accepts ``struct cnxk_bphy_cgx_msg`` messages which differ by type and payload.
-Message types along with description are listed below.
+Message types along with description are listed below. As for the usage examples please refer to
+``cnxk_bphy_cgx_dev_selftest()``.
 
 Get link information
 ~~~~~~~~~~~~~~~~~~~~
@@ -93,3 +94,19 @@ Message is used to start or stop accepting traffic.
 Message must have type set to ``CNXK_BPHY_CGX_MSG_TYPE_START_RXTX`` or
 ``CNXK_BPHY_CGX_MSG_TYPE_STOP_RXTX``. Former will enable traffic while the latter will
 do the opposite.
+
+Self test
+---------
+
+On EAL initialization, BPHY CGX/RPM devices will be probed and populated into
+the raw devices. The rawdev ID of the device can be obtained using invocation
+of ``rte_rawdev_get_dev_id("NAME:x")`` from the test application, where:
+
+- NAME is the desired subsystem: use "BPHY_CGX" for
+  RFOE module,
+- x is the device's bus id specified in "bus:device.func" (BDF) format.
+
+Use this identifier for further rawdev function calls.
+
+The driver's selftest rawdev API can be used to verify the BPHY CGX/RPM
+functionality.
index a8eafae..3da2244 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <roc_api.h>
 
+#include "cnxk_bphy_cgx.h"
 #include "rte_pmd_bphy.h"
 
 struct cnxk_bphy_cgx_queue {
@@ -196,6 +197,7 @@ static const struct rte_rawdev_ops cnxk_bphy_cgx_rawdev_ops = {
        .enqueue_bufs = cnxk_bphy_cgx_enqueue_bufs,
        .dequeue_bufs = cnxk_bphy_cgx_dequeue_bufs,
        .queue_count = cnxk_bphy_cgx_queue_count,
+       .dev_selftest = cnxk_bphy_cgx_dev_selftest,
 };
 
 static void
diff --git a/drivers/raw/cnxk_bphy/cnxk_bphy_cgx.h b/drivers/raw/cnxk_bphy/cnxk_bphy_cgx.h
new file mode 100644 (file)
index 0000000..fb6b31b
--- /dev/null
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#ifndef _CNXK_BPHY_CGX_H_
+#define _CNXK_BPHY_CGX_H_
+
+int cnxk_bphy_cgx_dev_selftest(uint16_t dev_id);
+
+#endif /* _CNXK_BPHY_CGX_H_ */
diff --git a/drivers/raw/cnxk_bphy/cnxk_bphy_cgx_test.c b/drivers/raw/cnxk_bphy/cnxk_bphy_cgx_test.c
new file mode 100644 (file)
index 0000000..cb4dd4b
--- /dev/null
@@ -0,0 +1,206 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+#include <stdint.h>
+
+#include <rte_cycles.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_rawdev.h>
+
+#include "cnxk_bphy_cgx.h"
+#include "rte_pmd_bphy.h"
+
+static int
+cnxk_bphy_cgx_enq_msg(uint16_t dev_id, unsigned int queue, void *msg)
+{
+       struct rte_rawdev_buf *bufs[1];
+       struct rte_rawdev_buf buf;
+       void *q;
+       int ret;
+
+       q = (void *)(size_t)queue;
+       buf.buf_addr = msg;
+       bufs[0] = &buf;
+
+       ret = rte_rawdev_enqueue_buffers(dev_id, bufs, 1, q);
+       if (ret < 0)
+               return ret;
+       if (ret != 1)
+               return -EIO;
+
+       return 0;
+}
+
+static int
+cnxk_bphy_cgx_deq_msg(uint16_t dev_id, unsigned int queue, void **msg)
+{
+       struct rte_rawdev_buf *bufs[1];
+       struct rte_rawdev_buf buf;
+       void *q;
+       int ret;
+
+       q = (void *)(size_t)queue;
+       bufs[0] = &buf;
+
+       ret = rte_rawdev_dequeue_buffers(dev_id, bufs, 1, q);
+       if (ret < 0)
+               return ret;
+       if (ret != 1)
+               return -EIO;
+
+       *msg = buf.buf_addr;
+
+       return 0;
+}
+
+static int
+cnxk_bphy_cgx_link_cond(uint16_t dev_id, unsigned int queue, int cond)
+{
+       int tries = 10, ret;
+
+       do {
+               struct cnxk_bphy_cgx_msg_link_info *link_info = NULL;
+               struct cnxk_bphy_cgx_msg msg;
+
+               msg.type = CNXK_BPHY_CGX_MSG_TYPE_GET_LINKINFO;
+               ret = cnxk_bphy_cgx_enq_msg(dev_id, queue, &msg);
+               if (ret)
+                       return ret;
+
+               ret = cnxk_bphy_cgx_deq_msg(dev_id, queue, (void **)&link_info);
+               if (ret)
+                       return ret;
+
+               if (link_info->link_up == cond) {
+                       rte_free(link_info);
+                       break;
+               }
+
+               rte_free(link_info);
+               rte_delay_ms(500);
+       } while (--tries);
+
+       if (tries)
+               return !!cond;
+
+       return -ETIMEDOUT;
+}
+
+int
+cnxk_bphy_cgx_dev_selftest(uint16_t dev_id)
+{
+       unsigned int queues, i;
+       int ret;
+
+       queues = rte_rawdev_queue_count(dev_id);
+       if (queues == 0)
+               return -ENODEV;
+
+       ret = rte_rawdev_start(dev_id);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < queues; i++) {
+               struct cnxk_bphy_cgx_msg_set_link_state link_state;
+               struct cnxk_bphy_cgx_msg msg;
+               unsigned int descs;
+
+               ret = rte_rawdev_queue_conf_get(dev_id, i, &descs,
+                                               sizeof(descs));
+               if (ret)
+                       break;
+               if (descs != 1) {
+                       RTE_LOG(ERR, PMD, "Wrong number of descs reported\n");
+                       ret = -ENODEV;
+                       break;
+               }
+
+               RTE_LOG(INFO, PMD, "Testing queue %d\n", i);
+
+               /* stop rx/tx */
+               msg.type = CNXK_BPHY_CGX_MSG_TYPE_STOP_RXTX;
+               ret = cnxk_bphy_cgx_enq_msg(dev_id, i, &msg);
+               if (ret) {
+                       RTE_LOG(ERR, PMD, "Failed to stop rx/tx\n");
+                       break;
+               }
+
+               /* start rx/tx */
+               msg.type = CNXK_BPHY_CGX_MSG_TYPE_START_RXTX;
+               ret = cnxk_bphy_cgx_enq_msg(dev_id, i, &msg);
+               if (ret) {
+                       RTE_LOG(ERR, PMD, "Failed to start rx/tx\n");
+                       break;
+               }
+
+               /* set link down */
+               link_state.state = false;
+               msg.type = CNXK_BPHY_CGX_MSG_TYPE_SET_LINK_STATE;
+               msg.data = &link_state;
+               ret = cnxk_bphy_cgx_enq_msg(dev_id, i, &msg);
+               if (ret) {
+                       RTE_LOG(ERR, PMD, "Failed to set link down\n");
+                       break;
+               }
+
+               ret = cnxk_bphy_cgx_link_cond(dev_id, i, 0);
+               if (ret != 0)
+                       RTE_LOG(ERR, PMD,
+                               "Timed out waiting for a link down\n");
+
+               /* set link up */
+               link_state.state = true;
+               msg.type = CNXK_BPHY_CGX_MSG_TYPE_SET_LINK_STATE;
+               msg.data = &link_state;
+               ret = cnxk_bphy_cgx_enq_msg(dev_id, i, &msg);
+               if (ret) {
+                       RTE_LOG(ERR, PMD, "Failed to set link up\n");
+                       break;
+               }
+
+               ret = cnxk_bphy_cgx_link_cond(dev_id, i, 1);
+               if (ret != 1)
+                       RTE_LOG(ERR, PMD, "Timed out waiting for a link up\n");
+
+               /* enable internal loopback */
+               msg.type = CNXK_BPHY_CGX_MSG_TYPE_INTLBK_ENABLE;
+               ret = cnxk_bphy_cgx_enq_msg(dev_id, i, &msg);
+               if (ret) {
+                       RTE_LOG(ERR, PMD, "Failed to enable internal lbk\n");
+                       break;
+               }
+
+               /* disable internal loopback */
+               msg.type = CNXK_BPHY_CGX_MSG_TYPE_INTLBK_DISABLE;
+               ret = cnxk_bphy_cgx_enq_msg(dev_id, i, &msg);
+               if (ret) {
+                       RTE_LOG(ERR, PMD, "Failed to disable internal lbk\n");
+                       break;
+               }
+
+               /* enable ptp */
+               msg.type = CNXK_BPHY_CGX_MSG_TYPE_PTP_RX_ENABLE;
+               ret = cnxk_bphy_cgx_enq_msg(dev_id, i, &msg);
+               /* ptp not available on RPM */
+               if (ret < 0 && ret != -ENOTSUP) {
+                       RTE_LOG(ERR, PMD, "Failed to enable ptp\n");
+                       break;
+               }
+               ret = 0;
+
+               /* disable ptp */
+               msg.type = CNXK_BPHY_CGX_MSG_TYPE_PTP_RX_DISABLE;
+               ret = cnxk_bphy_cgx_enq_msg(dev_id, i, &msg);
+               /* ptp not available on RPM */
+               if (ret < 0 && ret != -ENOTSUP) {
+                       RTE_LOG(ERR, PMD, "Failed to disable ptp\n");
+                       break;
+               }
+               ret = 0;
+       }
+
+       rte_rawdev_stop(dev_id);
+
+       return ret;
+}
index 0d65fc5..dc5558e 100644 (file)
@@ -5,5 +5,6 @@
 deps += ['bus_pci', 'common_cnxk', 'rawdev']
 sources = files(
         'cnxk_bphy_cgx.c',
+        'cnxk_bphy_cgx_test.c',
 )
 headers = files('rte_pmd_bphy.h')