@@ -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.
@@ -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
new file mode 100644
@@ -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_ */
new file mode 100644
@@ -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;
+}
@@ -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')