net/octeontx: add net device probe and remove
authorJerin Jacob <jerin.jacob@caviumnetworks.com>
Sun, 8 Oct 2017 12:44:15 +0000 (18:14 +0530)
committerFerruh Yigit <ferruh.yigit@intel.com>
Thu, 12 Oct 2017 00:36:57 +0000 (01:36 +0100)
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@caviumnetworks.com>
Signed-off-by: Santosh Shukla <santosh.shukla@caviumnetworks.com>
drivers/net/octeontx/Makefile
drivers/net/octeontx/octeontx_ethdev.c [new file with mode: 0644]
drivers/net/octeontx/octeontx_ethdev.h [new file with mode: 0644]

index 65de34c..e0eaf05 100644 (file)
@@ -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 (file)
index 0000000..1e509ea
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ *   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;
+
+       rte_event_dev_attr_get(evdev, RTE_EVENT_DEV_ATTR_PORT_COUNT,
+                       (uint32_t *)&pnum);
+       rte_event_dev_attr_get(evdev, RTE_EVENT_DEV_ATTR_QUEUE_COUNT,
+                       (uint32_t *)&qnum);
+       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 (file)
index 0000000..4c880f1
--- /dev/null
@@ -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__ */