xref: /dpdk/drivers/net/octeontx/octeontx_ethdev.c (revision ef7308fcb400647f1aaf30160ba5984f26f5a72b)
1f7be70e5SJerin Jacob /*
2f7be70e5SJerin Jacob  *   BSD LICENSE
3f7be70e5SJerin Jacob  *
4f7be70e5SJerin Jacob  *   Copyright (C) Cavium Inc. 2017. All rights reserved.
5f7be70e5SJerin Jacob  *
6f7be70e5SJerin Jacob  *   Redistribution and use in source and binary forms, with or without
7f7be70e5SJerin Jacob  *   modification, are permitted provided that the following conditions
8f7be70e5SJerin Jacob  *   are met:
9f7be70e5SJerin Jacob  *
10f7be70e5SJerin Jacob  *     * Redistributions of source code must retain the above copyright
11f7be70e5SJerin Jacob  *       notice, this list of conditions and the following disclaimer.
12f7be70e5SJerin Jacob  *     * Redistributions in binary form must reproduce the above copyright
13f7be70e5SJerin Jacob  *       notice, this list of conditions and the following disclaimer in
14f7be70e5SJerin Jacob  *       the documentation and/or other materials provided with the
15f7be70e5SJerin Jacob  *       distribution.
16f7be70e5SJerin Jacob  *     * Neither the name of Cavium networks nor the names of its
17f7be70e5SJerin Jacob  *       contributors may be used to endorse or promote products derived
18f7be70e5SJerin Jacob  *       from this software without specific prior written permission.
19f7be70e5SJerin Jacob  *
20f7be70e5SJerin Jacob  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21f7be70e5SJerin Jacob  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22f7be70e5SJerin Jacob  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23f7be70e5SJerin Jacob  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24f7be70e5SJerin Jacob  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25f7be70e5SJerin Jacob  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26f7be70e5SJerin Jacob  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27f7be70e5SJerin Jacob  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28f7be70e5SJerin Jacob  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29f7be70e5SJerin Jacob  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30f7be70e5SJerin Jacob  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31f7be70e5SJerin Jacob  */
32f7be70e5SJerin Jacob #include <stdio.h>
33f7be70e5SJerin Jacob #include <stdarg.h>
34f7be70e5SJerin Jacob #include <stdbool.h>
35f7be70e5SJerin Jacob #include <stdint.h>
36f7be70e5SJerin Jacob #include <string.h>
37f7be70e5SJerin Jacob #include <unistd.h>
38f7be70e5SJerin Jacob 
39f7be70e5SJerin Jacob #include <rte_alarm.h>
40f7be70e5SJerin Jacob #include <rte_branch_prediction.h>
41f7be70e5SJerin Jacob #include <rte_debug.h>
42f7be70e5SJerin Jacob #include <rte_devargs.h>
43f7be70e5SJerin Jacob #include <rte_dev.h>
44f7be70e5SJerin Jacob #include <rte_kvargs.h>
45f7be70e5SJerin Jacob #include <rte_malloc.h>
46f7be70e5SJerin Jacob #include <rte_prefetch.h>
47f7be70e5SJerin Jacob #include <rte_vdev.h>
48f7be70e5SJerin Jacob 
49f7be70e5SJerin Jacob #include "octeontx_ethdev.h"
50f7be70e5SJerin Jacob #include "octeontx_logs.h"
51f7be70e5SJerin Jacob 
52f7be70e5SJerin Jacob struct octeontx_vdev_init_params {
53f7be70e5SJerin Jacob 	uint8_t	nr_port;
54f7be70e5SJerin Jacob };
55f7be70e5SJerin Jacob 
564fac7c0aSJerin Jacob enum octeontx_link_speed {
574fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_SGMII,
584fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_XAUI,
594fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_RXAUI,
604fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_10G_R,
614fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_40G_R,
624fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_RESERVE1,
634fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_QSGMII,
644fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_RESERVE2
654fac7c0aSJerin Jacob };
664fac7c0aSJerin Jacob 
67f7be70e5SJerin Jacob /* Parse integer from integer argument */
68f7be70e5SJerin Jacob static int
69f7be70e5SJerin Jacob parse_integer_arg(const char *key __rte_unused,
70f7be70e5SJerin Jacob 		const char *value, void *extra_args)
71f7be70e5SJerin Jacob {
72f7be70e5SJerin Jacob 	int *i = (int *)extra_args;
73f7be70e5SJerin Jacob 
74f7be70e5SJerin Jacob 	*i = atoi(value);
75f7be70e5SJerin Jacob 	if (*i < 0) {
76f7be70e5SJerin Jacob 		octeontx_log_err("argument has to be positive.");
77f7be70e5SJerin Jacob 		return -1;
78f7be70e5SJerin Jacob 	}
79f7be70e5SJerin Jacob 
80f7be70e5SJerin Jacob 	return 0;
81f7be70e5SJerin Jacob }
82f7be70e5SJerin Jacob 
83f7be70e5SJerin Jacob static int
84f7be70e5SJerin Jacob octeontx_parse_vdev_init_params(struct octeontx_vdev_init_params *params,
85f7be70e5SJerin Jacob 				struct rte_vdev_device *dev)
86f7be70e5SJerin Jacob {
87f7be70e5SJerin Jacob 	struct rte_kvargs *kvlist = NULL;
88f7be70e5SJerin Jacob 	int ret = 0;
89f7be70e5SJerin Jacob 
90f7be70e5SJerin Jacob 	static const char * const octeontx_vdev_valid_params[] = {
91f7be70e5SJerin Jacob 		OCTEONTX_VDEV_NR_PORT_ARG,
92f7be70e5SJerin Jacob 		NULL
93f7be70e5SJerin Jacob 	};
94f7be70e5SJerin Jacob 
95f7be70e5SJerin Jacob 	const char *input_args = rte_vdev_device_args(dev);
96f7be70e5SJerin Jacob 	if (params == NULL)
97f7be70e5SJerin Jacob 		return -EINVAL;
98f7be70e5SJerin Jacob 
99f7be70e5SJerin Jacob 
100f7be70e5SJerin Jacob 	if (input_args) {
101f7be70e5SJerin Jacob 		kvlist = rte_kvargs_parse(input_args,
102f7be70e5SJerin Jacob 				octeontx_vdev_valid_params);
103f7be70e5SJerin Jacob 		if (kvlist == NULL)
104f7be70e5SJerin Jacob 			return -1;
105f7be70e5SJerin Jacob 
106f7be70e5SJerin Jacob 		ret = rte_kvargs_process(kvlist,
107f7be70e5SJerin Jacob 					OCTEONTX_VDEV_NR_PORT_ARG,
108f7be70e5SJerin Jacob 					&parse_integer_arg,
109f7be70e5SJerin Jacob 					&params->nr_port);
110f7be70e5SJerin Jacob 		if (ret < 0)
111f7be70e5SJerin Jacob 			goto free_kvlist;
112f7be70e5SJerin Jacob 	}
113f7be70e5SJerin Jacob 
114f7be70e5SJerin Jacob free_kvlist:
115f7be70e5SJerin Jacob 	rte_kvargs_free(kvlist);
116f7be70e5SJerin Jacob 	return ret;
117f7be70e5SJerin Jacob }
118f7be70e5SJerin Jacob 
119f18b146cSJerin Jacob static int
120f18b146cSJerin Jacob octeontx_port_open(struct octeontx_nic *nic)
121f18b146cSJerin Jacob {
122f18b146cSJerin Jacob 	octeontx_mbox_bgx_port_conf_t bgx_port_conf;
123f18b146cSJerin Jacob 	int res;
124f18b146cSJerin Jacob 
125f18b146cSJerin Jacob 	res = 0;
126f18b146cSJerin Jacob 
127f18b146cSJerin Jacob 	PMD_INIT_FUNC_TRACE();
128f18b146cSJerin Jacob 
129f18b146cSJerin Jacob 	res = octeontx_bgx_port_open(nic->port_id, &bgx_port_conf);
130f18b146cSJerin Jacob 	if (res < 0) {
131f18b146cSJerin Jacob 		octeontx_log_err("failed to open port %d", res);
132f18b146cSJerin Jacob 		return res;
133f18b146cSJerin Jacob 	}
134f18b146cSJerin Jacob 
135f18b146cSJerin Jacob 	nic->node = bgx_port_conf.node;
136f18b146cSJerin Jacob 	nic->port_ena = bgx_port_conf.enable;
137f18b146cSJerin Jacob 	nic->base_ichan = bgx_port_conf.base_chan;
138f18b146cSJerin Jacob 	nic->base_ochan = bgx_port_conf.base_chan;
139f18b146cSJerin Jacob 	nic->num_ichans = bgx_port_conf.num_chans;
140f18b146cSJerin Jacob 	nic->num_ochans = bgx_port_conf.num_chans;
141f18b146cSJerin Jacob 	nic->mtu = bgx_port_conf.mtu;
142f18b146cSJerin Jacob 	nic->bpen = bgx_port_conf.bpen;
143f18b146cSJerin Jacob 	nic->fcs_strip = bgx_port_conf.fcs_strip;
144f18b146cSJerin Jacob 	nic->bcast_mode = bgx_port_conf.bcast_mode;
145f18b146cSJerin Jacob 	nic->mcast_mode = bgx_port_conf.mcast_mode;
146f18b146cSJerin Jacob 	nic->speed	= bgx_port_conf.mode;
147f18b146cSJerin Jacob 
148f18b146cSJerin Jacob 	memcpy(&nic->mac_addr[0], &bgx_port_conf.macaddr[0], ETHER_ADDR_LEN);
149f18b146cSJerin Jacob 
150f18b146cSJerin Jacob 	octeontx_log_dbg("port opened %d", nic->port_id);
151f18b146cSJerin Jacob 	return res;
152f18b146cSJerin Jacob }
153f18b146cSJerin Jacob 
154f18b146cSJerin Jacob static void
155f18b146cSJerin Jacob octeontx_port_close(struct octeontx_nic *nic)
156f18b146cSJerin Jacob {
157f18b146cSJerin Jacob 	PMD_INIT_FUNC_TRACE();
158f18b146cSJerin Jacob 
159f18b146cSJerin Jacob 	octeontx_bgx_port_close(nic->port_id);
160f18b146cSJerin Jacob 	octeontx_log_dbg("port closed %d", nic->port_id);
161f18b146cSJerin Jacob }
162f18b146cSJerin Jacob 
16315bce35bSJerin Jacob static void
16415bce35bSJerin Jacob octeontx_port_promisc_set(struct octeontx_nic *nic, int en)
16515bce35bSJerin Jacob {
16615bce35bSJerin Jacob 	struct rte_eth_dev *dev;
16715bce35bSJerin Jacob 	int res;
16815bce35bSJerin Jacob 
16915bce35bSJerin Jacob 	res = 0;
17015bce35bSJerin Jacob 	PMD_INIT_FUNC_TRACE();
17115bce35bSJerin Jacob 	dev = nic->dev;
17215bce35bSJerin Jacob 
17315bce35bSJerin Jacob 	res = octeontx_bgx_port_promisc_set(nic->port_id, en);
17415bce35bSJerin Jacob 	if (res < 0)
17515bce35bSJerin Jacob 		octeontx_log_err("failed to set promiscuous mode %d",
17615bce35bSJerin Jacob 				nic->port_id);
17715bce35bSJerin Jacob 
17815bce35bSJerin Jacob 	/* Set proper flag for the mode */
17915bce35bSJerin Jacob 	dev->data->promiscuous = (en != 0) ? 1 : 0;
18015bce35bSJerin Jacob 
18115bce35bSJerin Jacob 	octeontx_log_dbg("port %d : promiscuous mode %s",
18215bce35bSJerin Jacob 			nic->port_id, en ? "set" : "unset");
18315bce35bSJerin Jacob }
18415bce35bSJerin Jacob 
18555389909SJerin Jacob static void
18655389909SJerin Jacob octeontx_port_stats(struct octeontx_nic *nic, struct rte_eth_stats *stats)
18755389909SJerin Jacob {
18855389909SJerin Jacob 	octeontx_mbox_bgx_port_stats_t bgx_stats;
18955389909SJerin Jacob 	int res;
19055389909SJerin Jacob 
19155389909SJerin Jacob 	PMD_INIT_FUNC_TRACE();
19255389909SJerin Jacob 
19355389909SJerin Jacob 	res = octeontx_bgx_port_stats(nic->port_id, &bgx_stats);
19455389909SJerin Jacob 	if (res < 0)
19555389909SJerin Jacob 		octeontx_log_err("failed to get port stats %d", nic->port_id);
19655389909SJerin Jacob 
19755389909SJerin Jacob 	stats->ipackets = bgx_stats.rx_packets;
19855389909SJerin Jacob 	stats->ibytes = bgx_stats.rx_bytes;
19955389909SJerin Jacob 	stats->imissed = bgx_stats.rx_dropped;
20055389909SJerin Jacob 	stats->ierrors = bgx_stats.rx_errors;
20155389909SJerin Jacob 	stats->opackets = bgx_stats.tx_packets;
20255389909SJerin Jacob 	stats->obytes = bgx_stats.tx_bytes;
20355389909SJerin Jacob 	stats->oerrors = bgx_stats.tx_errors;
20455389909SJerin Jacob 
20555389909SJerin Jacob 	octeontx_log_dbg("port%d stats inpkts=%" PRIx64 " outpkts=%" PRIx64 "",
20655389909SJerin Jacob 			nic->port_id, stats->ipackets, stats->opackets);
20755389909SJerin Jacob }
20855389909SJerin Jacob 
20955389909SJerin Jacob static void
21055389909SJerin Jacob octeontx_port_stats_clr(struct octeontx_nic *nic)
21155389909SJerin Jacob {
21255389909SJerin Jacob 	PMD_INIT_FUNC_TRACE();
21355389909SJerin Jacob 
21455389909SJerin Jacob 	octeontx_bgx_port_stats_clr(nic->port_id);
21555389909SJerin Jacob }
21655389909SJerin Jacob 
217f7be70e5SJerin Jacob static inline void
218f7be70e5SJerin Jacob devconf_set_default_sane_values(struct rte_event_dev_config *dev_conf,
219f7be70e5SJerin Jacob 				struct rte_event_dev_info *info)
220f7be70e5SJerin Jacob {
221f7be70e5SJerin Jacob 	memset(dev_conf, 0, sizeof(struct rte_event_dev_config));
222f7be70e5SJerin Jacob 	dev_conf->dequeue_timeout_ns = info->min_dequeue_timeout_ns;
223f7be70e5SJerin Jacob 
224f7be70e5SJerin Jacob 	dev_conf->nb_event_ports = info->max_event_ports;
225f7be70e5SJerin Jacob 	dev_conf->nb_event_queues = info->max_event_queues;
226f7be70e5SJerin Jacob 
227f7be70e5SJerin Jacob 	dev_conf->nb_event_queue_flows = info->max_event_queue_flows;
228f7be70e5SJerin Jacob 	dev_conf->nb_event_port_dequeue_depth =
229f7be70e5SJerin Jacob 			info->max_event_port_dequeue_depth;
230f7be70e5SJerin Jacob 	dev_conf->nb_event_port_enqueue_depth =
231f7be70e5SJerin Jacob 			info->max_event_port_enqueue_depth;
232f7be70e5SJerin Jacob 	dev_conf->nb_event_port_enqueue_depth =
233f7be70e5SJerin Jacob 			info->max_event_port_enqueue_depth;
234f7be70e5SJerin Jacob 	dev_conf->nb_events_limit =
235f7be70e5SJerin Jacob 			info->max_num_events;
236f7be70e5SJerin Jacob }
237f7be70e5SJerin Jacob 
2387742c55aSJerin Jacob static int
2397742c55aSJerin Jacob octeontx_dev_configure(struct rte_eth_dev *dev)
2407742c55aSJerin Jacob {
2417742c55aSJerin Jacob 	struct rte_eth_dev_data *data = dev->data;
2427742c55aSJerin Jacob 	struct rte_eth_conf *conf = &data->dev_conf;
2437742c55aSJerin Jacob 	struct rte_eth_rxmode *rxmode = &conf->rxmode;
2447742c55aSJerin Jacob 	struct rte_eth_txmode *txmode = &conf->txmode;
2457742c55aSJerin Jacob 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
2467742c55aSJerin Jacob 	int ret;
2477742c55aSJerin Jacob 
2487742c55aSJerin Jacob 	PMD_INIT_FUNC_TRACE();
2497742c55aSJerin Jacob 	RTE_SET_USED(conf);
2507742c55aSJerin Jacob 
2517742c55aSJerin Jacob 	if (!rte_eal_has_hugepages()) {
2527742c55aSJerin Jacob 		octeontx_log_err("huge page is not configured");
2537742c55aSJerin Jacob 		return -EINVAL;
2547742c55aSJerin Jacob 	}
2557742c55aSJerin Jacob 
2567742c55aSJerin Jacob 	if (txmode->mq_mode) {
2577742c55aSJerin Jacob 		octeontx_log_err("tx mq_mode DCB or VMDq not supported");
2587742c55aSJerin Jacob 		return -EINVAL;
2597742c55aSJerin Jacob 	}
2607742c55aSJerin Jacob 
2617742c55aSJerin Jacob 	if (rxmode->mq_mode != ETH_MQ_RX_NONE &&
2627742c55aSJerin Jacob 		rxmode->mq_mode != ETH_MQ_RX_RSS) {
2637742c55aSJerin Jacob 		octeontx_log_err("unsupported rx qmode %d", rxmode->mq_mode);
2647742c55aSJerin Jacob 		return -EINVAL;
2657742c55aSJerin Jacob 	}
2667742c55aSJerin Jacob 
2677742c55aSJerin Jacob 	if (!rxmode->hw_strip_crc) {
2687742c55aSJerin Jacob 		PMD_INIT_LOG(NOTICE, "can't disable hw crc strip");
2697742c55aSJerin Jacob 		rxmode->hw_strip_crc = 1;
2707742c55aSJerin Jacob 	}
2717742c55aSJerin Jacob 
2727742c55aSJerin Jacob 	if (rxmode->hw_ip_checksum) {
2737742c55aSJerin Jacob 		PMD_INIT_LOG(NOTICE, "rxcksum not supported");
2747742c55aSJerin Jacob 		rxmode->hw_ip_checksum = 0;
2757742c55aSJerin Jacob 	}
2767742c55aSJerin Jacob 
2777742c55aSJerin Jacob 	if (rxmode->split_hdr_size) {
2787742c55aSJerin Jacob 		octeontx_log_err("rxmode does not support split header");
2797742c55aSJerin Jacob 		return -EINVAL;
2807742c55aSJerin Jacob 	}
2817742c55aSJerin Jacob 
2827742c55aSJerin Jacob 	if (rxmode->hw_vlan_filter) {
2837742c55aSJerin Jacob 		octeontx_log_err("VLAN filter not supported");
2847742c55aSJerin Jacob 		return -EINVAL;
2857742c55aSJerin Jacob 	}
2867742c55aSJerin Jacob 
2877742c55aSJerin Jacob 	if (rxmode->hw_vlan_extend) {
2887742c55aSJerin Jacob 		octeontx_log_err("VLAN extended not supported");
2897742c55aSJerin Jacob 		return -EINVAL;
2907742c55aSJerin Jacob 	}
2917742c55aSJerin Jacob 
2927742c55aSJerin Jacob 	if (rxmode->enable_lro) {
2937742c55aSJerin Jacob 		octeontx_log_err("LRO not supported");
2947742c55aSJerin Jacob 		return -EINVAL;
2957742c55aSJerin Jacob 	}
2967742c55aSJerin Jacob 
2977742c55aSJerin Jacob 	if (conf->link_speeds & ETH_LINK_SPEED_FIXED) {
2987742c55aSJerin Jacob 		octeontx_log_err("setting link speed/duplex not supported");
2997742c55aSJerin Jacob 		return -EINVAL;
3007742c55aSJerin Jacob 	}
3017742c55aSJerin Jacob 
3027742c55aSJerin Jacob 	if (conf->dcb_capability_en) {
3037742c55aSJerin Jacob 		octeontx_log_err("DCB enable not supported");
3047742c55aSJerin Jacob 		return -EINVAL;
3057742c55aSJerin Jacob 	}
3067742c55aSJerin Jacob 
3077742c55aSJerin Jacob 	if (conf->fdir_conf.mode != RTE_FDIR_MODE_NONE) {
3087742c55aSJerin Jacob 		octeontx_log_err("flow director not supported");
3097742c55aSJerin Jacob 		return -EINVAL;
3107742c55aSJerin Jacob 	}
3117742c55aSJerin Jacob 
3127742c55aSJerin Jacob 	nic->num_tx_queues = dev->data->nb_tx_queues;
3137742c55aSJerin Jacob 
3147742c55aSJerin Jacob 	ret = octeontx_pko_channel_open(nic->port_id * PKO_VF_NUM_DQ,
3157742c55aSJerin Jacob 					nic->num_tx_queues,
3167742c55aSJerin Jacob 					nic->base_ochan);
3177742c55aSJerin Jacob 	if (ret) {
3187742c55aSJerin Jacob 		octeontx_log_err("failed to open channel %d no-of-txq %d",
3197742c55aSJerin Jacob 			   nic->base_ochan, nic->num_tx_queues);
3207742c55aSJerin Jacob 		return -EFAULT;
3217742c55aSJerin Jacob 	}
3227742c55aSJerin Jacob 
3237742c55aSJerin Jacob 	nic->pki.classifier_enable = false;
3247742c55aSJerin Jacob 	nic->pki.hash_enable = true;
3257742c55aSJerin Jacob 	nic->pki.initialized = false;
3267742c55aSJerin Jacob 
3277742c55aSJerin Jacob 	return 0;
3287742c55aSJerin Jacob }
3297742c55aSJerin Jacob 
33015bce35bSJerin Jacob static void
33115bce35bSJerin Jacob octeontx_dev_promisc_enable(struct rte_eth_dev *dev)
33215bce35bSJerin Jacob {
33315bce35bSJerin Jacob 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
33415bce35bSJerin Jacob 
33515bce35bSJerin Jacob 	PMD_INIT_FUNC_TRACE();
33615bce35bSJerin Jacob 	octeontx_port_promisc_set(nic, 1);
33715bce35bSJerin Jacob }
33815bce35bSJerin Jacob 
33915bce35bSJerin Jacob static void
34015bce35bSJerin Jacob octeontx_dev_promisc_disable(struct rte_eth_dev *dev)
34115bce35bSJerin Jacob {
34215bce35bSJerin Jacob 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
34315bce35bSJerin Jacob 
34415bce35bSJerin Jacob 	PMD_INIT_FUNC_TRACE();
34515bce35bSJerin Jacob 	octeontx_port_promisc_set(nic, 0);
34615bce35bSJerin Jacob }
34715bce35bSJerin Jacob 
3484fac7c0aSJerin Jacob static inline int
3494fac7c0aSJerin Jacob octeontx_atomic_write_link_status(struct rte_eth_dev *dev,
3504fac7c0aSJerin Jacob 				  struct rte_eth_link *link)
3514fac7c0aSJerin Jacob {
3524fac7c0aSJerin Jacob 	struct rte_eth_link *dst = &dev->data->dev_link;
3534fac7c0aSJerin Jacob 	struct rte_eth_link *src = link;
3544fac7c0aSJerin Jacob 
3554fac7c0aSJerin Jacob 	if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
3564fac7c0aSJerin Jacob 		*(uint64_t *)src) == 0)
3574fac7c0aSJerin Jacob 		return -1;
3584fac7c0aSJerin Jacob 
3594fac7c0aSJerin Jacob 	return 0;
3604fac7c0aSJerin Jacob }
3614fac7c0aSJerin Jacob 
3624fac7c0aSJerin Jacob static int
3634fac7c0aSJerin Jacob octeontx_port_link_status(struct octeontx_nic *nic)
3644fac7c0aSJerin Jacob {
3654fac7c0aSJerin Jacob 	int res;
3664fac7c0aSJerin Jacob 
3674fac7c0aSJerin Jacob 	PMD_INIT_FUNC_TRACE();
3684fac7c0aSJerin Jacob 	res = octeontx_bgx_port_link_status(nic->port_id);
3694fac7c0aSJerin Jacob 	if (res < 0) {
3704fac7c0aSJerin Jacob 		octeontx_log_err("failed to get port %d link status",
3714fac7c0aSJerin Jacob 				nic->port_id);
3724fac7c0aSJerin Jacob 		return res;
3734fac7c0aSJerin Jacob 	}
3744fac7c0aSJerin Jacob 
3754fac7c0aSJerin Jacob 	nic->link_up = (uint8_t)res;
3764fac7c0aSJerin Jacob 	octeontx_log_dbg("port %d link status %d", nic->port_id, nic->link_up);
3774fac7c0aSJerin Jacob 
3784fac7c0aSJerin Jacob 	return res;
3794fac7c0aSJerin Jacob }
3804fac7c0aSJerin Jacob 
3814fac7c0aSJerin Jacob /*
3824fac7c0aSJerin Jacob  * Return 0 means link status changed, -1 means not changed
3834fac7c0aSJerin Jacob  */
3844fac7c0aSJerin Jacob static int
3854fac7c0aSJerin Jacob octeontx_dev_link_update(struct rte_eth_dev *dev,
3864fac7c0aSJerin Jacob 			 int wait_to_complete __rte_unused)
3874fac7c0aSJerin Jacob {
3884fac7c0aSJerin Jacob 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
3894fac7c0aSJerin Jacob 	struct rte_eth_link link;
3904fac7c0aSJerin Jacob 	int res;
3914fac7c0aSJerin Jacob 
3924fac7c0aSJerin Jacob 	res = 0;
3934fac7c0aSJerin Jacob 	PMD_INIT_FUNC_TRACE();
3944fac7c0aSJerin Jacob 
3954fac7c0aSJerin Jacob 	res = octeontx_port_link_status(nic);
3964fac7c0aSJerin Jacob 	if (res < 0) {
3974fac7c0aSJerin Jacob 		octeontx_log_err("failed to request link status %d", res);
3984fac7c0aSJerin Jacob 		return res;
3994fac7c0aSJerin Jacob 	}
4004fac7c0aSJerin Jacob 
4014fac7c0aSJerin Jacob 	link.link_status = nic->link_up;
4024fac7c0aSJerin Jacob 
4034fac7c0aSJerin Jacob 	switch (nic->speed) {
4044fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_SGMII:
4054fac7c0aSJerin Jacob 		link.link_speed = ETH_SPEED_NUM_1G;
4064fac7c0aSJerin Jacob 		break;
4074fac7c0aSJerin Jacob 
4084fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_XAUI:
4094fac7c0aSJerin Jacob 		link.link_speed = ETH_SPEED_NUM_10G;
4104fac7c0aSJerin Jacob 		break;
4114fac7c0aSJerin Jacob 
4124fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_RXAUI:
4134fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_10G_R:
4144fac7c0aSJerin Jacob 		link.link_speed = ETH_SPEED_NUM_10G;
4154fac7c0aSJerin Jacob 		break;
4164fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_QSGMII:
4174fac7c0aSJerin Jacob 		link.link_speed = ETH_SPEED_NUM_5G;
4184fac7c0aSJerin Jacob 		break;
4194fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_40G_R:
4204fac7c0aSJerin Jacob 		link.link_speed = ETH_SPEED_NUM_40G;
4214fac7c0aSJerin Jacob 		break;
4224fac7c0aSJerin Jacob 
4234fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_RESERVE1:
4244fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_RESERVE2:
4254fac7c0aSJerin Jacob 	default:
4264fac7c0aSJerin Jacob 		octeontx_log_err("incorrect link speed %d", nic->speed);
4274fac7c0aSJerin Jacob 		break;
4284fac7c0aSJerin Jacob 	}
4294fac7c0aSJerin Jacob 
4304fac7c0aSJerin Jacob 	link.link_duplex = ETH_LINK_AUTONEG;
4314fac7c0aSJerin Jacob 	link.link_autoneg = ETH_LINK_SPEED_AUTONEG;
4324fac7c0aSJerin Jacob 
4334fac7c0aSJerin Jacob 	return octeontx_atomic_write_link_status(dev, &link);
4344fac7c0aSJerin Jacob }
4354fac7c0aSJerin Jacob 
4367c0347a2SJerin Jacob static void
43755389909SJerin Jacob octeontx_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
43855389909SJerin Jacob {
43955389909SJerin Jacob 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
44055389909SJerin Jacob 
44155389909SJerin Jacob 	PMD_INIT_FUNC_TRACE();
44255389909SJerin Jacob 	octeontx_port_stats(nic, stats);
44355389909SJerin Jacob }
44455389909SJerin Jacob 
44555389909SJerin Jacob static void
44655389909SJerin Jacob octeontx_dev_stats_reset(struct rte_eth_dev *dev)
44755389909SJerin Jacob {
44855389909SJerin Jacob 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
44955389909SJerin Jacob 
45055389909SJerin Jacob 	PMD_INIT_FUNC_TRACE();
45155389909SJerin Jacob 	octeontx_port_stats_clr(nic);
45255389909SJerin Jacob }
45355389909SJerin Jacob 
45455389909SJerin Jacob static void
455*ef7308fcSJerin Jacob octeontx_dev_default_mac_addr_set(struct rte_eth_dev *dev,
456*ef7308fcSJerin Jacob 					struct ether_addr *addr)
457*ef7308fcSJerin Jacob {
458*ef7308fcSJerin Jacob 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
459*ef7308fcSJerin Jacob 	int ret;
460*ef7308fcSJerin Jacob 
461*ef7308fcSJerin Jacob 	ret = octeontx_bgx_port_mac_set(nic->port_id, addr->addr_bytes);
462*ef7308fcSJerin Jacob 	if (ret != 0)
463*ef7308fcSJerin Jacob 		octeontx_log_err("failed to set MAC address on port %d",
464*ef7308fcSJerin Jacob 				nic->port_id);
465*ef7308fcSJerin Jacob }
466*ef7308fcSJerin Jacob 
467*ef7308fcSJerin Jacob static void
4687c0347a2SJerin Jacob octeontx_dev_info(struct rte_eth_dev *dev,
4697c0347a2SJerin Jacob 		struct rte_eth_dev_info *dev_info)
4707c0347a2SJerin Jacob {
4717c0347a2SJerin Jacob 	RTE_SET_USED(dev);
4727c0347a2SJerin Jacob 
4737c0347a2SJerin Jacob 	/* Autonegotiation may be disabled */
4747c0347a2SJerin Jacob 	dev_info->speed_capa = ETH_LINK_SPEED_FIXED;
4757c0347a2SJerin Jacob 	dev_info->speed_capa |= ETH_LINK_SPEED_10M | ETH_LINK_SPEED_100M |
4767c0347a2SJerin Jacob 			ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G |
4777c0347a2SJerin Jacob 			ETH_LINK_SPEED_40G;
4787c0347a2SJerin Jacob 
4797c0347a2SJerin Jacob 	dev_info->driver_name = RTE_STR(rte_octeontx_pmd);
4807c0347a2SJerin Jacob 	dev_info->max_mac_addrs = 1;
4817c0347a2SJerin Jacob 	dev_info->max_rx_pktlen = PKI_MAX_PKTLEN;
4827c0347a2SJerin Jacob 	dev_info->max_rx_queues = 1;
4837c0347a2SJerin Jacob 	dev_info->max_tx_queues = PKO_MAX_NUM_DQ;
4847c0347a2SJerin Jacob 	dev_info->min_rx_bufsize = 0;
4857c0347a2SJerin Jacob 	dev_info->pci_dev = NULL;
4867c0347a2SJerin Jacob 
4877c0347a2SJerin Jacob 	dev_info->default_rxconf = (struct rte_eth_rxconf) {
4887c0347a2SJerin Jacob 		.rx_free_thresh = 0,
4897c0347a2SJerin Jacob 		.rx_drop_en = 0,
4907c0347a2SJerin Jacob 	};
4917c0347a2SJerin Jacob 
4927c0347a2SJerin Jacob 	dev_info->default_txconf = (struct rte_eth_txconf) {
4937c0347a2SJerin Jacob 		.tx_free_thresh = 0,
4947c0347a2SJerin Jacob 		.txq_flags =
4957c0347a2SJerin Jacob 			ETH_TXQ_FLAGS_NOMULTSEGS |
4967c0347a2SJerin Jacob 			ETH_TXQ_FLAGS_NOOFFLOADS |
4977c0347a2SJerin Jacob 			ETH_TXQ_FLAGS_NOXSUMS,
4987c0347a2SJerin Jacob 	};
4997c0347a2SJerin Jacob 
5007c0347a2SJerin Jacob 	dev_info->tx_offload_capa = DEV_TX_OFFLOAD_MT_LOCKFREE;
5017c0347a2SJerin Jacob }
5027c0347a2SJerin Jacob 
503f18b146cSJerin Jacob /* Initialize and register driver with DPDK Application */
504f18b146cSJerin Jacob static const struct eth_dev_ops octeontx_dev_ops = {
5057742c55aSJerin Jacob 	.dev_configure		 = octeontx_dev_configure,
5067c0347a2SJerin Jacob 	.dev_infos_get		 = octeontx_dev_info,
50715bce35bSJerin Jacob 	.promiscuous_enable	 = octeontx_dev_promisc_enable,
50815bce35bSJerin Jacob 	.promiscuous_disable	 = octeontx_dev_promisc_disable,
5094fac7c0aSJerin Jacob 	.link_update		 = octeontx_dev_link_update,
51055389909SJerin Jacob 	.stats_get		 = octeontx_dev_stats_get,
51155389909SJerin Jacob 	.stats_reset		 = octeontx_dev_stats_reset,
512*ef7308fcSJerin Jacob 	.mac_addr_set		 = octeontx_dev_default_mac_addr_set,
513f18b146cSJerin Jacob };
514f18b146cSJerin Jacob 
515f7be70e5SJerin Jacob /* Create Ethdev interface per BGX LMAC ports */
516f7be70e5SJerin Jacob static int
517f7be70e5SJerin Jacob octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
518f7be70e5SJerin Jacob 			int socket_id)
519f7be70e5SJerin Jacob {
520f18b146cSJerin Jacob 	int res;
521f18b146cSJerin Jacob 	char octtx_name[OCTEONTX_MAX_NAME_LEN];
522f18b146cSJerin Jacob 	struct octeontx_nic *nic = NULL;
523f18b146cSJerin Jacob 	struct rte_eth_dev *eth_dev = NULL;
524f18b146cSJerin Jacob 	struct rte_eth_dev_data *data = NULL;
525f18b146cSJerin Jacob 	const char *name = rte_vdev_device_name(dev);
526f7be70e5SJerin Jacob 
527f18b146cSJerin Jacob 	PMD_INIT_FUNC_TRACE();
528f18b146cSJerin Jacob 
529f18b146cSJerin Jacob 	sprintf(octtx_name, "%s_%d", name, port);
530f18b146cSJerin Jacob 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
531f18b146cSJerin Jacob 		eth_dev = rte_eth_dev_attach_secondary(octtx_name);
532f18b146cSJerin Jacob 		if (eth_dev == NULL)
533f7be70e5SJerin Jacob 			return -ENODEV;
534f18b146cSJerin Jacob 
535f18b146cSJerin Jacob 		return 0;
536f18b146cSJerin Jacob 	}
537f18b146cSJerin Jacob 
538f18b146cSJerin Jacob 	data = rte_zmalloc_socket(octtx_name, sizeof(*data), 0, socket_id);
539f18b146cSJerin Jacob 	if (data == NULL) {
540f18b146cSJerin Jacob 		octeontx_log_err("failed to allocate devdata");
541f18b146cSJerin Jacob 		res = -ENOMEM;
542f18b146cSJerin Jacob 		goto err;
543f18b146cSJerin Jacob 	}
544f18b146cSJerin Jacob 
545f18b146cSJerin Jacob 	nic = rte_zmalloc_socket(octtx_name, sizeof(*nic), 0, socket_id);
546f18b146cSJerin Jacob 	if (nic == NULL) {
547f18b146cSJerin Jacob 		octeontx_log_err("failed to allocate nic structure");
548f18b146cSJerin Jacob 		res = -ENOMEM;
549f18b146cSJerin Jacob 		goto err;
550f18b146cSJerin Jacob 	}
551f18b146cSJerin Jacob 
552f18b146cSJerin Jacob 	nic->port_id = port;
553f18b146cSJerin Jacob 	nic->evdev = evdev;
554f18b146cSJerin Jacob 
555f18b146cSJerin Jacob 	res = octeontx_port_open(nic);
556f18b146cSJerin Jacob 	if (res < 0)
557f18b146cSJerin Jacob 		goto err;
558f18b146cSJerin Jacob 
559f18b146cSJerin Jacob 	/* Rx side port configuration */
560f18b146cSJerin Jacob 	res = octeontx_pki_port_open(port);
561f18b146cSJerin Jacob 	if (res != 0) {
562f18b146cSJerin Jacob 		octeontx_log_err("failed to open PKI port %d", port);
563f18b146cSJerin Jacob 		res = -ENODEV;
564f18b146cSJerin Jacob 		goto err;
565f18b146cSJerin Jacob 	}
566f18b146cSJerin Jacob 
567f18b146cSJerin Jacob 	/* Reserve an ethdev entry */
568f18b146cSJerin Jacob 	eth_dev = rte_eth_dev_allocate(octtx_name);
569f18b146cSJerin Jacob 	if (eth_dev == NULL) {
570f18b146cSJerin Jacob 		octeontx_log_err("failed to allocate rte_eth_dev");
571f18b146cSJerin Jacob 		res = -ENOMEM;
572f18b146cSJerin Jacob 		goto err;
573f18b146cSJerin Jacob 	}
574f18b146cSJerin Jacob 
575f18b146cSJerin Jacob 	eth_dev->device = &dev->device;
576f18b146cSJerin Jacob 	eth_dev->intr_handle = NULL;
577f18b146cSJerin Jacob 	eth_dev->data->kdrv = RTE_KDRV_NONE;
578f18b146cSJerin Jacob 	eth_dev->data->numa_node = dev->device.numa_node;
579f18b146cSJerin Jacob 
580f18b146cSJerin Jacob 	rte_memcpy(data, (eth_dev)->data, sizeof(*data));
581f18b146cSJerin Jacob 	data->dev_private = nic;
582f18b146cSJerin Jacob 
583f18b146cSJerin Jacob 	data->port_id = eth_dev->data->port_id;
584f18b146cSJerin Jacob 	snprintf(data->name, sizeof(data->name), "%s", eth_dev->data->name);
585f18b146cSJerin Jacob 
586f18b146cSJerin Jacob 	nic->ev_queues = 1;
587f18b146cSJerin Jacob 	nic->ev_ports = 1;
588f18b146cSJerin Jacob 
589f18b146cSJerin Jacob 	data->dev_link.link_status = ETH_LINK_DOWN;
590f18b146cSJerin Jacob 	data->dev_started = 0;
591f18b146cSJerin Jacob 	data->promiscuous = 0;
592f18b146cSJerin Jacob 	data->all_multicast = 0;
593f18b146cSJerin Jacob 	data->scattered_rx = 0;
594f18b146cSJerin Jacob 
595f18b146cSJerin Jacob 	data->mac_addrs = rte_zmalloc_socket(octtx_name, ETHER_ADDR_LEN, 0,
596f18b146cSJerin Jacob 							socket_id);
597f18b146cSJerin Jacob 	if (data->mac_addrs == NULL) {
598f18b146cSJerin Jacob 		octeontx_log_err("failed to allocate memory for mac_addrs");
599f18b146cSJerin Jacob 		res = -ENOMEM;
600f18b146cSJerin Jacob 		goto err;
601f18b146cSJerin Jacob 	}
602f18b146cSJerin Jacob 
603f18b146cSJerin Jacob 	eth_dev->data = data;
604f18b146cSJerin Jacob 	eth_dev->dev_ops = &octeontx_dev_ops;
605f18b146cSJerin Jacob 
606f18b146cSJerin Jacob 	/* Finally save ethdev pointer to the NIC structure */
607f18b146cSJerin Jacob 	nic->dev = eth_dev;
608f18b146cSJerin Jacob 
609f18b146cSJerin Jacob 	if (nic->port_id != data->port_id) {
610f18b146cSJerin Jacob 		octeontx_log_err("eth_dev->port_id (%d) is diff to orig (%d)",
611f18b146cSJerin Jacob 				data->port_id, nic->port_id);
612f18b146cSJerin Jacob 		res = -EINVAL;
613f18b146cSJerin Jacob 		goto err;
614f18b146cSJerin Jacob 	}
615f18b146cSJerin Jacob 
616f18b146cSJerin Jacob 	/* Update port_id mac to eth_dev */
617f18b146cSJerin Jacob 	memcpy(data->mac_addrs, nic->mac_addr, ETHER_ADDR_LEN);
618f18b146cSJerin Jacob 
619f18b146cSJerin Jacob 	PMD_INIT_LOG(DEBUG, "ethdev info: ");
620f18b146cSJerin Jacob 	PMD_INIT_LOG(DEBUG, "port %d, port_ena %d ochan %d num_ochan %d tx_q %d",
621f18b146cSJerin Jacob 				nic->port_id, nic->port_ena,
622f18b146cSJerin Jacob 				nic->base_ochan, nic->num_ochans,
623f18b146cSJerin Jacob 				nic->num_tx_queues);
624f18b146cSJerin Jacob 	PMD_INIT_LOG(DEBUG, "speed %d mtu %d", nic->speed, nic->mtu);
625f18b146cSJerin Jacob 
626f18b146cSJerin Jacob 	return data->port_id;
627f18b146cSJerin Jacob 
628f18b146cSJerin Jacob err:
629f18b146cSJerin Jacob 	if (port)
630f18b146cSJerin Jacob 		octeontx_port_close(nic);
631f18b146cSJerin Jacob 
632f18b146cSJerin Jacob 	if (eth_dev != NULL) {
633f18b146cSJerin Jacob 		rte_free(eth_dev->data->mac_addrs);
634f18b146cSJerin Jacob 		rte_free(data);
635f18b146cSJerin Jacob 		rte_free(nic);
636f18b146cSJerin Jacob 		rte_eth_dev_release_port(eth_dev);
637f18b146cSJerin Jacob 	}
638f18b146cSJerin Jacob 
639f18b146cSJerin Jacob 	return res;
640f7be70e5SJerin Jacob }
641f7be70e5SJerin Jacob 
642f7be70e5SJerin Jacob /* Un initialize octeontx device */
643f7be70e5SJerin Jacob static int
644f7be70e5SJerin Jacob octeontx_remove(struct rte_vdev_device *dev)
645f7be70e5SJerin Jacob {
646f7be70e5SJerin Jacob 	char octtx_name[OCTEONTX_MAX_NAME_LEN];
647f7be70e5SJerin Jacob 	struct rte_eth_dev *eth_dev = NULL;
648f7be70e5SJerin Jacob 	struct octeontx_nic *nic = NULL;
649f7be70e5SJerin Jacob 	int i;
650f7be70e5SJerin Jacob 
651f7be70e5SJerin Jacob 	if (dev == NULL)
652f7be70e5SJerin Jacob 		return -EINVAL;
653f7be70e5SJerin Jacob 
654f7be70e5SJerin Jacob 	for (i = 0; i < OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT; i++) {
655f7be70e5SJerin Jacob 		sprintf(octtx_name, "eth_octeontx_%d", i);
656f7be70e5SJerin Jacob 
657f7be70e5SJerin Jacob 		/* reserve an ethdev entry */
658f7be70e5SJerin Jacob 		eth_dev = rte_eth_dev_allocated(octtx_name);
659f7be70e5SJerin Jacob 		if (eth_dev == NULL)
660f7be70e5SJerin Jacob 			return -ENODEV;
661f7be70e5SJerin Jacob 
662f7be70e5SJerin Jacob 		nic = octeontx_pmd_priv(eth_dev);
663f7be70e5SJerin Jacob 		rte_event_dev_stop(nic->evdev);
664f7be70e5SJerin Jacob 		PMD_INIT_LOG(INFO, "Closing octeontx device %s", octtx_name);
665f7be70e5SJerin Jacob 
666f7be70e5SJerin Jacob 		rte_free(eth_dev->data->mac_addrs);
667f7be70e5SJerin Jacob 		rte_free(eth_dev->data->dev_private);
668f7be70e5SJerin Jacob 		rte_free(eth_dev->data);
669f7be70e5SJerin Jacob 		rte_eth_dev_release_port(eth_dev);
670f7be70e5SJerin Jacob 		rte_event_dev_close(nic->evdev);
671f7be70e5SJerin Jacob 	}
672f7be70e5SJerin Jacob 
673f7be70e5SJerin Jacob 	/* Free FC resource */
674f7be70e5SJerin Jacob 	octeontx_pko_fc_free();
675f7be70e5SJerin Jacob 
676f7be70e5SJerin Jacob 	return 0;
677f7be70e5SJerin Jacob }
678f7be70e5SJerin Jacob 
679f7be70e5SJerin Jacob /* Initialize octeontx device */
680f7be70e5SJerin Jacob static int
681f7be70e5SJerin Jacob octeontx_probe(struct rte_vdev_device *dev)
682f7be70e5SJerin Jacob {
683f7be70e5SJerin Jacob 	const char *dev_name;
684f7be70e5SJerin Jacob 	static int probe_once;
685f7be70e5SJerin Jacob 	uint8_t socket_id, qlist;
686f7be70e5SJerin Jacob 	int tx_vfcnt, port_id, evdev, qnum, pnum, res, i;
687f7be70e5SJerin Jacob 	struct rte_event_dev_config dev_conf;
688f7be70e5SJerin Jacob 	const char *eventdev_name = "event_octeontx";
689f7be70e5SJerin Jacob 	struct rte_event_dev_info info;
690f7be70e5SJerin Jacob 
691f7be70e5SJerin Jacob 	struct octeontx_vdev_init_params init_params = {
692f7be70e5SJerin Jacob 		OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT
693f7be70e5SJerin Jacob 	};
694f7be70e5SJerin Jacob 
695f7be70e5SJerin Jacob 	dev_name = rte_vdev_device_name(dev);
696f7be70e5SJerin Jacob 	res = octeontx_parse_vdev_init_params(&init_params, dev);
697f7be70e5SJerin Jacob 	if (res < 0)
698f7be70e5SJerin Jacob 		return -EINVAL;
699f7be70e5SJerin Jacob 
700f7be70e5SJerin Jacob 	if (init_params.nr_port > OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT) {
701f7be70e5SJerin Jacob 		octeontx_log_err("nr_port (%d) > max (%d)", init_params.nr_port,
702f7be70e5SJerin Jacob 				OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT);
703f7be70e5SJerin Jacob 		return -ENOTSUP;
704f7be70e5SJerin Jacob 	}
705f7be70e5SJerin Jacob 
706f7be70e5SJerin Jacob 	PMD_INIT_LOG(DEBUG, "initializing %s pmd", dev_name);
707f7be70e5SJerin Jacob 
708f7be70e5SJerin Jacob 	socket_id = rte_socket_id();
709f7be70e5SJerin Jacob 
710f7be70e5SJerin Jacob 	tx_vfcnt = octeontx_pko_vf_count();
711f7be70e5SJerin Jacob 
712f7be70e5SJerin Jacob 	if (tx_vfcnt < init_params.nr_port) {
713f7be70e5SJerin Jacob 		octeontx_log_err("not enough PKO (%d) for port number (%d)",
714f7be70e5SJerin Jacob 				tx_vfcnt, init_params.nr_port);
715f7be70e5SJerin Jacob 		return -EINVAL;
716f7be70e5SJerin Jacob 	}
717f7be70e5SJerin Jacob 	evdev = rte_event_dev_get_dev_id(eventdev_name);
718f7be70e5SJerin Jacob 	if (evdev < 0) {
719f7be70e5SJerin Jacob 		octeontx_log_err("eventdev %s not found", eventdev_name);
720f7be70e5SJerin Jacob 		return -ENODEV;
721f7be70e5SJerin Jacob 	}
722f7be70e5SJerin Jacob 
723f7be70e5SJerin Jacob 	res = rte_event_dev_info_get(evdev, &info);
724f7be70e5SJerin Jacob 	if (res < 0) {
725f7be70e5SJerin Jacob 		octeontx_log_err("failed to eventdev info %d", res);
726f7be70e5SJerin Jacob 		return -EINVAL;
727f7be70e5SJerin Jacob 	}
728f7be70e5SJerin Jacob 
729f7be70e5SJerin Jacob 	PMD_INIT_LOG(DEBUG, "max_queue %d max_port %d",
730f7be70e5SJerin Jacob 			info.max_event_queues, info.max_event_ports);
731f7be70e5SJerin Jacob 
732f7be70e5SJerin Jacob 	if (octeontx_pko_init_fc(tx_vfcnt))
733f7be70e5SJerin Jacob 		return -ENOMEM;
734f7be70e5SJerin Jacob 
735f7be70e5SJerin Jacob 	devconf_set_default_sane_values(&dev_conf, &info);
736f7be70e5SJerin Jacob 	res = rte_event_dev_configure(evdev, &dev_conf);
737f7be70e5SJerin Jacob 	if (res < 0)
738f7be70e5SJerin Jacob 		goto parse_error;
739f7be70e5SJerin Jacob 
740f7be70e5SJerin Jacob 	rte_event_dev_attr_get(evdev, RTE_EVENT_DEV_ATTR_PORT_COUNT,
741f7be70e5SJerin Jacob 			(uint32_t *)&pnum);
742f7be70e5SJerin Jacob 	rte_event_dev_attr_get(evdev, RTE_EVENT_DEV_ATTR_QUEUE_COUNT,
743f7be70e5SJerin Jacob 			(uint32_t *)&qnum);
744f7be70e5SJerin Jacob 	if (pnum < qnum) {
745f7be70e5SJerin Jacob 		octeontx_log_err("too few event ports (%d) for event_q(%d)",
746f7be70e5SJerin Jacob 				pnum, qnum);
747f7be70e5SJerin Jacob 		res = -EINVAL;
748f7be70e5SJerin Jacob 		goto parse_error;
749f7be70e5SJerin Jacob 	}
750f7be70e5SJerin Jacob 	if (pnum > qnum) {
751f7be70e5SJerin Jacob 		/*
752f7be70e5SJerin Jacob 		 * We don't poll on event ports
753f7be70e5SJerin Jacob 		 * that do not have any queues assigned.
754f7be70e5SJerin Jacob 		 */
755f7be70e5SJerin Jacob 		pnum = qnum;
756f7be70e5SJerin Jacob 		PMD_INIT_LOG(INFO,
757f7be70e5SJerin Jacob 			"reducing number of active event ports to %d", pnum);
758f7be70e5SJerin Jacob 	}
759f7be70e5SJerin Jacob 	for (i = 0; i < qnum; i++) {
760f7be70e5SJerin Jacob 		res = rte_event_queue_setup(evdev, i, NULL);
761f7be70e5SJerin Jacob 		if (res < 0) {
762f7be70e5SJerin Jacob 			octeontx_log_err("failed to setup event_q(%d): res %d",
763f7be70e5SJerin Jacob 					i, res);
764f7be70e5SJerin Jacob 			goto parse_error;
765f7be70e5SJerin Jacob 		}
766f7be70e5SJerin Jacob 	}
767f7be70e5SJerin Jacob 
768f7be70e5SJerin Jacob 	for (i = 0; i < pnum; i++) {
769f7be70e5SJerin Jacob 		res = rte_event_port_setup(evdev, i, NULL);
770f7be70e5SJerin Jacob 		if (res < 0) {
771f7be70e5SJerin Jacob 			res = -ENODEV;
772f7be70e5SJerin Jacob 			octeontx_log_err("failed to setup ev port(%d) res=%d",
773f7be70e5SJerin Jacob 						i, res);
774f7be70e5SJerin Jacob 			goto parse_error;
775f7be70e5SJerin Jacob 		}
776f7be70e5SJerin Jacob 		/* Link one queue to one event port */
777f7be70e5SJerin Jacob 		qlist = i;
778f7be70e5SJerin Jacob 		res = rte_event_port_link(evdev, i, &qlist, NULL, 1);
779f7be70e5SJerin Jacob 		if (res < 0) {
780f7be70e5SJerin Jacob 			res = -ENODEV;
781f7be70e5SJerin Jacob 			octeontx_log_err("failed to link port (%d): res=%d",
782f7be70e5SJerin Jacob 					i, res);
783f7be70e5SJerin Jacob 			goto parse_error;
784f7be70e5SJerin Jacob 		}
785f7be70e5SJerin Jacob 	}
786f7be70e5SJerin Jacob 
787f7be70e5SJerin Jacob 	/* Create ethdev interface */
788f7be70e5SJerin Jacob 	for (i = 0; i < init_params.nr_port; i++) {
789f7be70e5SJerin Jacob 		port_id = octeontx_create(dev, i, evdev, socket_id);
790f7be70e5SJerin Jacob 		if (port_id < 0) {
791f7be70e5SJerin Jacob 			octeontx_log_err("failed to create device %s",
792f7be70e5SJerin Jacob 					dev_name);
793f7be70e5SJerin Jacob 			res = -ENODEV;
794f7be70e5SJerin Jacob 			goto parse_error;
795f7be70e5SJerin Jacob 		}
796f7be70e5SJerin Jacob 
797f7be70e5SJerin Jacob 		PMD_INIT_LOG(INFO, "created ethdev %s for port %d", dev_name,
798f7be70e5SJerin Jacob 					port_id);
799f7be70e5SJerin Jacob 	}
800f7be70e5SJerin Jacob 
801f7be70e5SJerin Jacob 	if (probe_once) {
802f7be70e5SJerin Jacob 		octeontx_log_err("interface %s not supported", dev_name);
803f7be70e5SJerin Jacob 		octeontx_remove(dev);
804f7be70e5SJerin Jacob 		res = -ENOTSUP;
805f7be70e5SJerin Jacob 		goto parse_error;
806f7be70e5SJerin Jacob 	}
807f7be70e5SJerin Jacob 	probe_once = 1;
808f7be70e5SJerin Jacob 
809f7be70e5SJerin Jacob 	return 0;
810f7be70e5SJerin Jacob 
811f7be70e5SJerin Jacob parse_error:
812f7be70e5SJerin Jacob 	octeontx_pko_fc_free();
813f7be70e5SJerin Jacob 	return res;
814f7be70e5SJerin Jacob }
815f7be70e5SJerin Jacob 
816f7be70e5SJerin Jacob static struct rte_vdev_driver octeontx_pmd_drv = {
817f7be70e5SJerin Jacob 	.probe = octeontx_probe,
818f7be70e5SJerin Jacob 	.remove = octeontx_remove,
819f7be70e5SJerin Jacob };
820f7be70e5SJerin Jacob 
821f7be70e5SJerin Jacob RTE_PMD_REGISTER_VDEV(OCTEONTX_PMD, octeontx_pmd_drv);
822f7be70e5SJerin Jacob RTE_PMD_REGISTER_ALIAS(OCTEONTX_PMD, eth_octeontx);
823f7be70e5SJerin Jacob RTE_PMD_REGISTER_PARAM_STRING(OCTEONTX_PMD, "nr_port=<int> ");
824