[dpdk-dev] [PATCH 11/26] net/octeontx: add eth device probe and remove

Jerin Jacob jerin.jacob at caviumnetworks.com
Thu Aug 31 16:54:21 CEST 2017


An octeontx ethdev device consists of multiple PKO VF devices, a PKI
VF device and multiple SSOVF devices which shared between eventdev.
This patch adds a vdev based device called "eth_octeontx" which
will create multiple ethernet ports based on "nr_port" or maximum
physical ports are available in the system.

Signed-off-by: Jerin Jacob <jerin.jacob at caviumnetworks.com>
Co-authored-by: Santosh Shukla <santosh.shukla at caviumnetworks.com>
---
 drivers/net/octeontx/Makefile          |   1 +
 drivers/net/octeontx/octeontx_ethdev.c | 321 +++++++++++++++++++++++++++++++++
 drivers/net/octeontx/octeontx_ethdev.h |  94 ++++++++++
 3 files changed, 416 insertions(+)
 create mode 100644 drivers/net/octeontx/octeontx_ethdev.c
 create mode 100644 drivers/net/octeontx/octeontx_ethdev.h

diff --git a/drivers/net/octeontx/Makefile b/drivers/net/octeontx/Makefile
index 65de34c87..e0eaf059c 100644
--- a/drivers/net/octeontx/Makefile
+++ b/drivers/net/octeontx/Makefile
@@ -53,6 +53,7 @@ VPATH += $(SRCDIR)/base
 SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_pkovf.c
 SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_pkivf.c
 SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_bgx.c
+SRCS-$(CONFIG_RTE_LIBRTE_OCTEONTX_PMD) += octeontx_ethdev.c
 
 LDLIBS += -lrte_eventdev
 LDLIBS += -lrte_pmd_octeontx_ssovf
diff --git a/drivers/net/octeontx/octeontx_ethdev.c b/drivers/net/octeontx/octeontx_ethdev.c
new file mode 100644
index 000000000..621035233
--- /dev/null
+++ b/drivers/net/octeontx/octeontx_ethdev.c
@@ -0,0 +1,321 @@
+/*
+ *   BSD LICENSE
+ *
+ *   Copyright (C) Cavium Inc. 2017. All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Cavium networks nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rte_alarm.h>
+#include <rte_branch_prediction.h>
+#include <rte_debug.h>
+#include <rte_devargs.h>
+#include <rte_dev.h>
+#include <rte_kvargs.h>
+#include <rte_malloc.h>
+#include <rte_prefetch.h>
+#include <rte_vdev.h>
+
+#include "octeontx_ethdev.h"
+#include "octeontx_logs.h"
+
+struct octeontx_vdev_init_params {
+	uint8_t	nr_port;
+};
+
+/* Parse integer from integer argument */
+static int
+parse_integer_arg(const char *key __rte_unused,
+		const char *value, void *extra_args)
+{
+	int *i = (int *)extra_args;
+
+	*i = atoi(value);
+	if (*i < 0) {
+		octeontx_log_err("argument has to be positive.");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+octeontx_parse_vdev_init_params(struct octeontx_vdev_init_params *params,
+				struct rte_vdev_device *dev)
+{
+	struct rte_kvargs *kvlist = NULL;
+	int ret = 0;
+
+	static const char * const octeontx_vdev_valid_params[] = {
+		OCTEONTX_VDEV_NR_PORT_ARG,
+		NULL
+	};
+
+	const char *input_args = rte_vdev_device_args(dev);
+	if (params == NULL)
+		return -EINVAL;
+
+
+	if (input_args) {
+		kvlist = rte_kvargs_parse(input_args,
+				octeontx_vdev_valid_params);
+		if (kvlist == NULL)
+			return -1;
+
+		ret = rte_kvargs_process(kvlist,
+					OCTEONTX_VDEV_NR_PORT_ARG,
+					&parse_integer_arg,
+					&params->nr_port);
+		if (ret < 0)
+			goto free_kvlist;
+	}
+
+free_kvlist:
+	rte_kvargs_free(kvlist);
+	return ret;
+}
+
+static inline void
+devconf_set_default_sane_values(struct rte_event_dev_config *dev_conf,
+				struct rte_event_dev_info *info)
+{
+	memset(dev_conf, 0, sizeof(struct rte_event_dev_config));
+	dev_conf->dequeue_timeout_ns = info->min_dequeue_timeout_ns;
+
+	dev_conf->nb_event_ports = info->max_event_ports;
+	dev_conf->nb_event_queues = info->max_event_queues;
+
+	dev_conf->nb_event_queue_flows = info->max_event_queue_flows;
+	dev_conf->nb_event_port_dequeue_depth =
+			info->max_event_port_dequeue_depth;
+	dev_conf->nb_event_port_enqueue_depth =
+			info->max_event_port_enqueue_depth;
+	dev_conf->nb_event_port_enqueue_depth =
+			info->max_event_port_enqueue_depth;
+	dev_conf->nb_events_limit =
+			info->max_num_events;
+}
+
+/* Create Ethdev interface per BGX LMAC ports */
+static int
+octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
+			int socket_id)
+{
+	RTE_SET_USED(dev);
+	RTE_SET_USED(port);
+	RTE_SET_USED(evdev);
+	RTE_SET_USED(socket_id);
+
+	return -ENODEV;
+}
+
+/* Un initialize octeontx device */
+static int
+octeontx_remove(struct rte_vdev_device *dev)
+{
+	char octtx_name[OCTEONTX_MAX_NAME_LEN];
+	struct rte_eth_dev *eth_dev = NULL;
+	struct octeontx_nic *nic = NULL;
+	int i;
+
+	if (dev == NULL)
+		return -EINVAL;
+
+	for (i = 0; i < OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT; i++) {
+		sprintf(octtx_name, "eth_octeontx_%d", i);
+
+		/* reserve an ethdev entry */
+		eth_dev = rte_eth_dev_allocated(octtx_name);
+		if (eth_dev == NULL)
+			return -ENODEV;
+
+		nic = octeontx_pmd_priv(eth_dev);
+		rte_event_dev_stop(nic->evdev);
+		PMD_INIT_LOG(INFO, "Closing octeontx device %s", octtx_name);
+
+		rte_free(eth_dev->data->mac_addrs);
+		rte_free(eth_dev->data->dev_private);
+		rte_free(eth_dev->data);
+		rte_eth_dev_release_port(eth_dev);
+		rte_event_dev_close(nic->evdev);
+	}
+
+	/* Free FC resource */
+	octeontx_pko_fc_free();
+
+	return 0;
+}
+
+/* Initialize octeontx device */
+static int
+octeontx_probe(struct rte_vdev_device *dev)
+{
+	const char *dev_name;
+	static int probe_once;
+	uint8_t socket_id, qlist;
+	int tx_vfcnt, port_id, evdev, qnum, pnum, res, i;
+	struct rte_event_dev_config dev_conf;
+	const char *eventdev_name = "event_octeontx";
+	struct rte_event_dev_info info;
+
+	struct octeontx_vdev_init_params init_params = {
+		OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT
+	};
+
+	dev_name = rte_vdev_device_name(dev);
+	res = octeontx_parse_vdev_init_params(&init_params, dev);
+	if (res < 0)
+		return -EINVAL;
+
+	if (init_params.nr_port > OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT) {
+		octeontx_log_err("nr_port (%d) > max (%d)", init_params.nr_port,
+				OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT);
+		return -ENOTSUP;
+	}
+
+	PMD_INIT_LOG(DEBUG, "initializing %s pmd", dev_name);
+
+	socket_id = rte_socket_id();
+
+	tx_vfcnt = octeontx_pko_vf_count();
+
+	if (tx_vfcnt < init_params.nr_port) {
+		octeontx_log_err("not enough PKO (%d) for port number (%d)",
+				tx_vfcnt, init_params.nr_port);
+		return -EINVAL;
+	}
+	evdev = rte_event_dev_get_dev_id(eventdev_name);
+	if (evdev < 0) {
+		octeontx_log_err("eventdev %s not found", eventdev_name);
+		return -ENODEV;
+	}
+
+	res = rte_event_dev_info_get(evdev, &info);
+	if (res < 0) {
+		octeontx_log_err("failed to eventdev info %d", res);
+		return -EINVAL;
+	}
+
+	PMD_INIT_LOG(DEBUG, "max_queue %d max_port %d",
+			info.max_event_queues, info.max_event_ports);
+
+	if (octeontx_pko_init_fc(tx_vfcnt))
+		return -ENOMEM;
+
+	devconf_set_default_sane_values(&dev_conf, &info);
+	res = rte_event_dev_configure(evdev, &dev_conf);
+	if (res < 0)
+		goto parse_error;
+
+	qnum = rte_event_queue_count(evdev);
+	pnum = rte_event_port_count(evdev);
+	if (pnum < qnum) {
+		octeontx_log_err("too few event ports (%d) for event_q(%d)",
+				pnum, qnum);
+		res = -EINVAL;
+		goto parse_error;
+	}
+	if (pnum > qnum) {
+		/*
+		 * We don't poll on event ports
+		 * that do not have any queues assigned.
+		 */
+		pnum = qnum;
+		PMD_INIT_LOG(INFO,
+			"reducing number of active event ports to %d", pnum);
+	}
+	for (i = 0; i < qnum; i++) {
+		res = rte_event_queue_setup(evdev, i, NULL);
+		if (res < 0) {
+			octeontx_log_err("failed to setup event_q(%d): res %d",
+					i, res);
+			goto parse_error;
+		}
+	}
+
+	for (i = 0; i < pnum; i++) {
+		res = rte_event_port_setup(evdev, i, NULL);
+		if (res < 0) {
+			res = -ENODEV;
+			octeontx_log_err("failed to setup ev port(%d) res=%d",
+						i, res);
+			goto parse_error;
+		}
+		/* Link one queue to one event port */
+		qlist = i;
+		res = rte_event_port_link(evdev, i, &qlist, NULL, 1);
+		if (res < 0) {
+			res = -ENODEV;
+			octeontx_log_err("failed to link port (%d): res=%d",
+					i, res);
+			goto parse_error;
+		}
+	}
+
+	/* Create ethdev interface */
+	for (i = 0; i < init_params.nr_port; i++) {
+		port_id = octeontx_create(dev, i, evdev, socket_id);
+		if (port_id < 0) {
+			octeontx_log_err("failed to create device %s",
+					dev_name);
+			res = -ENODEV;
+			goto parse_error;
+		}
+
+		PMD_INIT_LOG(INFO, "created ethdev %s for port %d", dev_name,
+					port_id);
+	}
+
+	if (probe_once) {
+		octeontx_log_err("interface %s not supported", dev_name);
+		octeontx_remove(dev);
+		res = -ENOTSUP;
+		goto parse_error;
+	}
+	probe_once = 1;
+
+	return 0;
+
+parse_error:
+	octeontx_pko_fc_free();
+	return res;
+}
+
+static struct rte_vdev_driver octeontx_pmd_drv = {
+	.probe = octeontx_probe,
+	.remove = octeontx_remove,
+};
+
+RTE_PMD_REGISTER_VDEV(OCTEONTX_PMD, octeontx_pmd_drv);
+RTE_PMD_REGISTER_ALIAS(OCTEONTX_PMD, eth_octeontx);
+RTE_PMD_REGISTER_PARAM_STRING(OCTEONTX_PMD, "nr_port=<int> ");
diff --git a/drivers/net/octeontx/octeontx_ethdev.h b/drivers/net/octeontx/octeontx_ethdev.h
new file mode 100644
index 000000000..4c880f187
--- /dev/null
+++ b/drivers/net/octeontx/octeontx_ethdev.h
@@ -0,0 +1,94 @@
+/*
+ *   BSD LICENSE
+ *
+ *   Copyright (C) Cavium Inc. 2017. All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Cavium networks nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef	__OCTEONTX_ETHDEV_H__
+#define	__OCTEONTX_ETHDEV_H__
+
+#include <stdbool.h>
+
+#include <rte_common.h>
+#include <rte_ethdev.h>
+#include <rte_eventdev.h>
+#include <rte_mempool.h>
+#include <rte_memory.h>
+
+#include <octeontx_fpavf.h>
+
+#include "base/octeontx_bgx.h"
+#include "base/octeontx_pki_var.h"
+#include "base/octeontx_pkivf.h"
+#include "base/octeontx_pkovf.h"
+#include "base/octeontx_io.h"
+
+#define OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT	12
+#define OCTEONTX_VDEV_NR_PORT_ARG		("nr_port")
+#define OCTEONTX_MAX_NAME_LEN			32
+
+static inline struct octeontx_nic *
+octeontx_pmd_priv(struct rte_eth_dev *dev)
+{
+	return dev->data->dev_private;
+}
+
+/* Octeontx ethdev nic */
+struct octeontx_nic {
+	struct rte_eth_dev *dev;
+	int node;
+	int port_id;
+	int port_ena;
+	int base_ichan;
+	int num_ichans;
+	int base_ochan;
+	int num_ochans;
+	uint8_t evdev;
+	uint8_t bpen;
+	uint8_t fcs_strip;
+	uint8_t bcast_mode;
+	uint8_t mcast_mode;
+	uint16_t num_tx_queues;
+	uint64_t hwcap;
+	uint8_t link_up;
+	uint8_t	duplex;
+	uint8_t speed;
+	uint16_t mtu;
+	uint8_t mac_addr[ETHER_ADDR_LEN];
+	/* Rx port parameters */
+	struct {
+		bool classifier_enable;
+		bool hash_enable;
+		bool initialized;
+	} pki;
+
+	uint16_t ev_queues;
+	uint16_t ev_ports;
+} __rte_cache_aligned;
+
+#endif /* __OCTEONTX_ETHDEV_H__ */
-- 
2.14.1



More information about the dev mailing list