xref: /dpdk/drivers/net/octeontx/octeontx_ethdev.c (revision 4fac7c0a147e4eae91aa527ee51ad70616b14182)
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 
56*4fac7c0aSJerin Jacob enum octeontx_link_speed {
57*4fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_SGMII,
58*4fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_XAUI,
59*4fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_RXAUI,
60*4fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_10G_R,
61*4fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_40G_R,
62*4fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_RESERVE1,
63*4fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_QSGMII,
64*4fac7c0aSJerin Jacob 	OCTEONTX_LINK_SPEED_RESERVE2
65*4fac7c0aSJerin Jacob };
66*4fac7c0aSJerin 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 
163f7be70e5SJerin Jacob static inline void
164f7be70e5SJerin Jacob devconf_set_default_sane_values(struct rte_event_dev_config *dev_conf,
165f7be70e5SJerin Jacob 				struct rte_event_dev_info *info)
166f7be70e5SJerin Jacob {
167f7be70e5SJerin Jacob 	memset(dev_conf, 0, sizeof(struct rte_event_dev_config));
168f7be70e5SJerin Jacob 	dev_conf->dequeue_timeout_ns = info->min_dequeue_timeout_ns;
169f7be70e5SJerin Jacob 
170f7be70e5SJerin Jacob 	dev_conf->nb_event_ports = info->max_event_ports;
171f7be70e5SJerin Jacob 	dev_conf->nb_event_queues = info->max_event_queues;
172f7be70e5SJerin Jacob 
173f7be70e5SJerin Jacob 	dev_conf->nb_event_queue_flows = info->max_event_queue_flows;
174f7be70e5SJerin Jacob 	dev_conf->nb_event_port_dequeue_depth =
175f7be70e5SJerin Jacob 			info->max_event_port_dequeue_depth;
176f7be70e5SJerin Jacob 	dev_conf->nb_event_port_enqueue_depth =
177f7be70e5SJerin Jacob 			info->max_event_port_enqueue_depth;
178f7be70e5SJerin Jacob 	dev_conf->nb_event_port_enqueue_depth =
179f7be70e5SJerin Jacob 			info->max_event_port_enqueue_depth;
180f7be70e5SJerin Jacob 	dev_conf->nb_events_limit =
181f7be70e5SJerin Jacob 			info->max_num_events;
182f7be70e5SJerin Jacob }
183f7be70e5SJerin Jacob 
1847742c55aSJerin Jacob static int
1857742c55aSJerin Jacob octeontx_dev_configure(struct rte_eth_dev *dev)
1867742c55aSJerin Jacob {
1877742c55aSJerin Jacob 	struct rte_eth_dev_data *data = dev->data;
1887742c55aSJerin Jacob 	struct rte_eth_conf *conf = &data->dev_conf;
1897742c55aSJerin Jacob 	struct rte_eth_rxmode *rxmode = &conf->rxmode;
1907742c55aSJerin Jacob 	struct rte_eth_txmode *txmode = &conf->txmode;
1917742c55aSJerin Jacob 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
1927742c55aSJerin Jacob 	int ret;
1937742c55aSJerin Jacob 
1947742c55aSJerin Jacob 	PMD_INIT_FUNC_TRACE();
1957742c55aSJerin Jacob 	RTE_SET_USED(conf);
1967742c55aSJerin Jacob 
1977742c55aSJerin Jacob 	if (!rte_eal_has_hugepages()) {
1987742c55aSJerin Jacob 		octeontx_log_err("huge page is not configured");
1997742c55aSJerin Jacob 		return -EINVAL;
2007742c55aSJerin Jacob 	}
2017742c55aSJerin Jacob 
2027742c55aSJerin Jacob 	if (txmode->mq_mode) {
2037742c55aSJerin Jacob 		octeontx_log_err("tx mq_mode DCB or VMDq not supported");
2047742c55aSJerin Jacob 		return -EINVAL;
2057742c55aSJerin Jacob 	}
2067742c55aSJerin Jacob 
2077742c55aSJerin Jacob 	if (rxmode->mq_mode != ETH_MQ_RX_NONE &&
2087742c55aSJerin Jacob 		rxmode->mq_mode != ETH_MQ_RX_RSS) {
2097742c55aSJerin Jacob 		octeontx_log_err("unsupported rx qmode %d", rxmode->mq_mode);
2107742c55aSJerin Jacob 		return -EINVAL;
2117742c55aSJerin Jacob 	}
2127742c55aSJerin Jacob 
2137742c55aSJerin Jacob 	if (!rxmode->hw_strip_crc) {
2147742c55aSJerin Jacob 		PMD_INIT_LOG(NOTICE, "can't disable hw crc strip");
2157742c55aSJerin Jacob 		rxmode->hw_strip_crc = 1;
2167742c55aSJerin Jacob 	}
2177742c55aSJerin Jacob 
2187742c55aSJerin Jacob 	if (rxmode->hw_ip_checksum) {
2197742c55aSJerin Jacob 		PMD_INIT_LOG(NOTICE, "rxcksum not supported");
2207742c55aSJerin Jacob 		rxmode->hw_ip_checksum = 0;
2217742c55aSJerin Jacob 	}
2227742c55aSJerin Jacob 
2237742c55aSJerin Jacob 	if (rxmode->split_hdr_size) {
2247742c55aSJerin Jacob 		octeontx_log_err("rxmode does not support split header");
2257742c55aSJerin Jacob 		return -EINVAL;
2267742c55aSJerin Jacob 	}
2277742c55aSJerin Jacob 
2287742c55aSJerin Jacob 	if (rxmode->hw_vlan_filter) {
2297742c55aSJerin Jacob 		octeontx_log_err("VLAN filter not supported");
2307742c55aSJerin Jacob 		return -EINVAL;
2317742c55aSJerin Jacob 	}
2327742c55aSJerin Jacob 
2337742c55aSJerin Jacob 	if (rxmode->hw_vlan_extend) {
2347742c55aSJerin Jacob 		octeontx_log_err("VLAN extended not supported");
2357742c55aSJerin Jacob 		return -EINVAL;
2367742c55aSJerin Jacob 	}
2377742c55aSJerin Jacob 
2387742c55aSJerin Jacob 	if (rxmode->enable_lro) {
2397742c55aSJerin Jacob 		octeontx_log_err("LRO not supported");
2407742c55aSJerin Jacob 		return -EINVAL;
2417742c55aSJerin Jacob 	}
2427742c55aSJerin Jacob 
2437742c55aSJerin Jacob 	if (conf->link_speeds & ETH_LINK_SPEED_FIXED) {
2447742c55aSJerin Jacob 		octeontx_log_err("setting link speed/duplex not supported");
2457742c55aSJerin Jacob 		return -EINVAL;
2467742c55aSJerin Jacob 	}
2477742c55aSJerin Jacob 
2487742c55aSJerin Jacob 	if (conf->dcb_capability_en) {
2497742c55aSJerin Jacob 		octeontx_log_err("DCB enable not supported");
2507742c55aSJerin Jacob 		return -EINVAL;
2517742c55aSJerin Jacob 	}
2527742c55aSJerin Jacob 
2537742c55aSJerin Jacob 	if (conf->fdir_conf.mode != RTE_FDIR_MODE_NONE) {
2547742c55aSJerin Jacob 		octeontx_log_err("flow director not supported");
2557742c55aSJerin Jacob 		return -EINVAL;
2567742c55aSJerin Jacob 	}
2577742c55aSJerin Jacob 
2587742c55aSJerin Jacob 	nic->num_tx_queues = dev->data->nb_tx_queues;
2597742c55aSJerin Jacob 
2607742c55aSJerin Jacob 	ret = octeontx_pko_channel_open(nic->port_id * PKO_VF_NUM_DQ,
2617742c55aSJerin Jacob 					nic->num_tx_queues,
2627742c55aSJerin Jacob 					nic->base_ochan);
2637742c55aSJerin Jacob 	if (ret) {
2647742c55aSJerin Jacob 		octeontx_log_err("failed to open channel %d no-of-txq %d",
2657742c55aSJerin Jacob 			   nic->base_ochan, nic->num_tx_queues);
2667742c55aSJerin Jacob 		return -EFAULT;
2677742c55aSJerin Jacob 	}
2687742c55aSJerin Jacob 
2697742c55aSJerin Jacob 	nic->pki.classifier_enable = false;
2707742c55aSJerin Jacob 	nic->pki.hash_enable = true;
2717742c55aSJerin Jacob 	nic->pki.initialized = false;
2727742c55aSJerin Jacob 
2737742c55aSJerin Jacob 	return 0;
2747742c55aSJerin Jacob }
2757742c55aSJerin Jacob 
276*4fac7c0aSJerin Jacob static inline int
277*4fac7c0aSJerin Jacob octeontx_atomic_write_link_status(struct rte_eth_dev *dev,
278*4fac7c0aSJerin Jacob 				  struct rte_eth_link *link)
279*4fac7c0aSJerin Jacob {
280*4fac7c0aSJerin Jacob 	struct rte_eth_link *dst = &dev->data->dev_link;
281*4fac7c0aSJerin Jacob 	struct rte_eth_link *src = link;
282*4fac7c0aSJerin Jacob 
283*4fac7c0aSJerin Jacob 	if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
284*4fac7c0aSJerin Jacob 		*(uint64_t *)src) == 0)
285*4fac7c0aSJerin Jacob 		return -1;
286*4fac7c0aSJerin Jacob 
287*4fac7c0aSJerin Jacob 	return 0;
288*4fac7c0aSJerin Jacob }
289*4fac7c0aSJerin Jacob 
290*4fac7c0aSJerin Jacob static int
291*4fac7c0aSJerin Jacob octeontx_port_link_status(struct octeontx_nic *nic)
292*4fac7c0aSJerin Jacob {
293*4fac7c0aSJerin Jacob 	int res;
294*4fac7c0aSJerin Jacob 
295*4fac7c0aSJerin Jacob 	PMD_INIT_FUNC_TRACE();
296*4fac7c0aSJerin Jacob 	res = octeontx_bgx_port_link_status(nic->port_id);
297*4fac7c0aSJerin Jacob 	if (res < 0) {
298*4fac7c0aSJerin Jacob 		octeontx_log_err("failed to get port %d link status",
299*4fac7c0aSJerin Jacob 				nic->port_id);
300*4fac7c0aSJerin Jacob 		return res;
301*4fac7c0aSJerin Jacob 	}
302*4fac7c0aSJerin Jacob 
303*4fac7c0aSJerin Jacob 	nic->link_up = (uint8_t)res;
304*4fac7c0aSJerin Jacob 	octeontx_log_dbg("port %d link status %d", nic->port_id, nic->link_up);
305*4fac7c0aSJerin Jacob 
306*4fac7c0aSJerin Jacob 	return res;
307*4fac7c0aSJerin Jacob }
308*4fac7c0aSJerin Jacob 
309*4fac7c0aSJerin Jacob /*
310*4fac7c0aSJerin Jacob  * Return 0 means link status changed, -1 means not changed
311*4fac7c0aSJerin Jacob  */
312*4fac7c0aSJerin Jacob static int
313*4fac7c0aSJerin Jacob octeontx_dev_link_update(struct rte_eth_dev *dev,
314*4fac7c0aSJerin Jacob 			 int wait_to_complete __rte_unused)
315*4fac7c0aSJerin Jacob {
316*4fac7c0aSJerin Jacob 	struct octeontx_nic *nic = octeontx_pmd_priv(dev);
317*4fac7c0aSJerin Jacob 	struct rte_eth_link link;
318*4fac7c0aSJerin Jacob 	int res;
319*4fac7c0aSJerin Jacob 
320*4fac7c0aSJerin Jacob 	res = 0;
321*4fac7c0aSJerin Jacob 	PMD_INIT_FUNC_TRACE();
322*4fac7c0aSJerin Jacob 
323*4fac7c0aSJerin Jacob 	res = octeontx_port_link_status(nic);
324*4fac7c0aSJerin Jacob 	if (res < 0) {
325*4fac7c0aSJerin Jacob 		octeontx_log_err("failed to request link status %d", res);
326*4fac7c0aSJerin Jacob 		return res;
327*4fac7c0aSJerin Jacob 	}
328*4fac7c0aSJerin Jacob 
329*4fac7c0aSJerin Jacob 	link.link_status = nic->link_up;
330*4fac7c0aSJerin Jacob 
331*4fac7c0aSJerin Jacob 	switch (nic->speed) {
332*4fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_SGMII:
333*4fac7c0aSJerin Jacob 		link.link_speed = ETH_SPEED_NUM_1G;
334*4fac7c0aSJerin Jacob 		break;
335*4fac7c0aSJerin Jacob 
336*4fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_XAUI:
337*4fac7c0aSJerin Jacob 		link.link_speed = ETH_SPEED_NUM_10G;
338*4fac7c0aSJerin Jacob 		break;
339*4fac7c0aSJerin Jacob 
340*4fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_RXAUI:
341*4fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_10G_R:
342*4fac7c0aSJerin Jacob 		link.link_speed = ETH_SPEED_NUM_10G;
343*4fac7c0aSJerin Jacob 		break;
344*4fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_QSGMII:
345*4fac7c0aSJerin Jacob 		link.link_speed = ETH_SPEED_NUM_5G;
346*4fac7c0aSJerin Jacob 		break;
347*4fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_40G_R:
348*4fac7c0aSJerin Jacob 		link.link_speed = ETH_SPEED_NUM_40G;
349*4fac7c0aSJerin Jacob 		break;
350*4fac7c0aSJerin Jacob 
351*4fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_RESERVE1:
352*4fac7c0aSJerin Jacob 	case OCTEONTX_LINK_SPEED_RESERVE2:
353*4fac7c0aSJerin Jacob 	default:
354*4fac7c0aSJerin Jacob 		octeontx_log_err("incorrect link speed %d", nic->speed);
355*4fac7c0aSJerin Jacob 		break;
356*4fac7c0aSJerin Jacob 	}
357*4fac7c0aSJerin Jacob 
358*4fac7c0aSJerin Jacob 	link.link_duplex = ETH_LINK_AUTONEG;
359*4fac7c0aSJerin Jacob 	link.link_autoneg = ETH_LINK_SPEED_AUTONEG;
360*4fac7c0aSJerin Jacob 
361*4fac7c0aSJerin Jacob 	return octeontx_atomic_write_link_status(dev, &link);
362*4fac7c0aSJerin Jacob }
363*4fac7c0aSJerin Jacob 
3647c0347a2SJerin Jacob static void
3657c0347a2SJerin Jacob octeontx_dev_info(struct rte_eth_dev *dev,
3667c0347a2SJerin Jacob 		struct rte_eth_dev_info *dev_info)
3677c0347a2SJerin Jacob {
3687c0347a2SJerin Jacob 	RTE_SET_USED(dev);
3697c0347a2SJerin Jacob 
3707c0347a2SJerin Jacob 	/* Autonegotiation may be disabled */
3717c0347a2SJerin Jacob 	dev_info->speed_capa = ETH_LINK_SPEED_FIXED;
3727c0347a2SJerin Jacob 	dev_info->speed_capa |= ETH_LINK_SPEED_10M | ETH_LINK_SPEED_100M |
3737c0347a2SJerin Jacob 			ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G |
3747c0347a2SJerin Jacob 			ETH_LINK_SPEED_40G;
3757c0347a2SJerin Jacob 
3767c0347a2SJerin Jacob 	dev_info->driver_name = RTE_STR(rte_octeontx_pmd);
3777c0347a2SJerin Jacob 	dev_info->max_mac_addrs = 1;
3787c0347a2SJerin Jacob 	dev_info->max_rx_pktlen = PKI_MAX_PKTLEN;
3797c0347a2SJerin Jacob 	dev_info->max_rx_queues = 1;
3807c0347a2SJerin Jacob 	dev_info->max_tx_queues = PKO_MAX_NUM_DQ;
3817c0347a2SJerin Jacob 	dev_info->min_rx_bufsize = 0;
3827c0347a2SJerin Jacob 	dev_info->pci_dev = NULL;
3837c0347a2SJerin Jacob 
3847c0347a2SJerin Jacob 	dev_info->default_rxconf = (struct rte_eth_rxconf) {
3857c0347a2SJerin Jacob 		.rx_free_thresh = 0,
3867c0347a2SJerin Jacob 		.rx_drop_en = 0,
3877c0347a2SJerin Jacob 	};
3887c0347a2SJerin Jacob 
3897c0347a2SJerin Jacob 	dev_info->default_txconf = (struct rte_eth_txconf) {
3907c0347a2SJerin Jacob 		.tx_free_thresh = 0,
3917c0347a2SJerin Jacob 		.txq_flags =
3927c0347a2SJerin Jacob 			ETH_TXQ_FLAGS_NOMULTSEGS |
3937c0347a2SJerin Jacob 			ETH_TXQ_FLAGS_NOOFFLOADS |
3947c0347a2SJerin Jacob 			ETH_TXQ_FLAGS_NOXSUMS,
3957c0347a2SJerin Jacob 	};
3967c0347a2SJerin Jacob 
3977c0347a2SJerin Jacob 	dev_info->tx_offload_capa = DEV_TX_OFFLOAD_MT_LOCKFREE;
3987c0347a2SJerin Jacob }
3997c0347a2SJerin Jacob 
400f18b146cSJerin Jacob /* Initialize and register driver with DPDK Application */
401f18b146cSJerin Jacob static const struct eth_dev_ops octeontx_dev_ops = {
4027742c55aSJerin Jacob 	.dev_configure		 = octeontx_dev_configure,
4037c0347a2SJerin Jacob 	.dev_infos_get		 = octeontx_dev_info,
404*4fac7c0aSJerin Jacob 	.link_update		 = octeontx_dev_link_update,
405f18b146cSJerin Jacob };
406f18b146cSJerin Jacob 
407f7be70e5SJerin Jacob /* Create Ethdev interface per BGX LMAC ports */
408f7be70e5SJerin Jacob static int
409f7be70e5SJerin Jacob octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
410f7be70e5SJerin Jacob 			int socket_id)
411f7be70e5SJerin Jacob {
412f18b146cSJerin Jacob 	int res;
413f18b146cSJerin Jacob 	char octtx_name[OCTEONTX_MAX_NAME_LEN];
414f18b146cSJerin Jacob 	struct octeontx_nic *nic = NULL;
415f18b146cSJerin Jacob 	struct rte_eth_dev *eth_dev = NULL;
416f18b146cSJerin Jacob 	struct rte_eth_dev_data *data = NULL;
417f18b146cSJerin Jacob 	const char *name = rte_vdev_device_name(dev);
418f7be70e5SJerin Jacob 
419f18b146cSJerin Jacob 	PMD_INIT_FUNC_TRACE();
420f18b146cSJerin Jacob 
421f18b146cSJerin Jacob 	sprintf(octtx_name, "%s_%d", name, port);
422f18b146cSJerin Jacob 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
423f18b146cSJerin Jacob 		eth_dev = rte_eth_dev_attach_secondary(octtx_name);
424f18b146cSJerin Jacob 		if (eth_dev == NULL)
425f7be70e5SJerin Jacob 			return -ENODEV;
426f18b146cSJerin Jacob 
427f18b146cSJerin Jacob 		return 0;
428f18b146cSJerin Jacob 	}
429f18b146cSJerin Jacob 
430f18b146cSJerin Jacob 	data = rte_zmalloc_socket(octtx_name, sizeof(*data), 0, socket_id);
431f18b146cSJerin Jacob 	if (data == NULL) {
432f18b146cSJerin Jacob 		octeontx_log_err("failed to allocate devdata");
433f18b146cSJerin Jacob 		res = -ENOMEM;
434f18b146cSJerin Jacob 		goto err;
435f18b146cSJerin Jacob 	}
436f18b146cSJerin Jacob 
437f18b146cSJerin Jacob 	nic = rte_zmalloc_socket(octtx_name, sizeof(*nic), 0, socket_id);
438f18b146cSJerin Jacob 	if (nic == NULL) {
439f18b146cSJerin Jacob 		octeontx_log_err("failed to allocate nic structure");
440f18b146cSJerin Jacob 		res = -ENOMEM;
441f18b146cSJerin Jacob 		goto err;
442f18b146cSJerin Jacob 	}
443f18b146cSJerin Jacob 
444f18b146cSJerin Jacob 	nic->port_id = port;
445f18b146cSJerin Jacob 	nic->evdev = evdev;
446f18b146cSJerin Jacob 
447f18b146cSJerin Jacob 	res = octeontx_port_open(nic);
448f18b146cSJerin Jacob 	if (res < 0)
449f18b146cSJerin Jacob 		goto err;
450f18b146cSJerin Jacob 
451f18b146cSJerin Jacob 	/* Rx side port configuration */
452f18b146cSJerin Jacob 	res = octeontx_pki_port_open(port);
453f18b146cSJerin Jacob 	if (res != 0) {
454f18b146cSJerin Jacob 		octeontx_log_err("failed to open PKI port %d", port);
455f18b146cSJerin Jacob 		res = -ENODEV;
456f18b146cSJerin Jacob 		goto err;
457f18b146cSJerin Jacob 	}
458f18b146cSJerin Jacob 
459f18b146cSJerin Jacob 	/* Reserve an ethdev entry */
460f18b146cSJerin Jacob 	eth_dev = rte_eth_dev_allocate(octtx_name);
461f18b146cSJerin Jacob 	if (eth_dev == NULL) {
462f18b146cSJerin Jacob 		octeontx_log_err("failed to allocate rte_eth_dev");
463f18b146cSJerin Jacob 		res = -ENOMEM;
464f18b146cSJerin Jacob 		goto err;
465f18b146cSJerin Jacob 	}
466f18b146cSJerin Jacob 
467f18b146cSJerin Jacob 	eth_dev->device = &dev->device;
468f18b146cSJerin Jacob 	eth_dev->intr_handle = NULL;
469f18b146cSJerin Jacob 	eth_dev->data->kdrv = RTE_KDRV_NONE;
470f18b146cSJerin Jacob 	eth_dev->data->numa_node = dev->device.numa_node;
471f18b146cSJerin Jacob 
472f18b146cSJerin Jacob 	rte_memcpy(data, (eth_dev)->data, sizeof(*data));
473f18b146cSJerin Jacob 	data->dev_private = nic;
474f18b146cSJerin Jacob 
475f18b146cSJerin Jacob 	data->port_id = eth_dev->data->port_id;
476f18b146cSJerin Jacob 	snprintf(data->name, sizeof(data->name), "%s", eth_dev->data->name);
477f18b146cSJerin Jacob 
478f18b146cSJerin Jacob 	nic->ev_queues = 1;
479f18b146cSJerin Jacob 	nic->ev_ports = 1;
480f18b146cSJerin Jacob 
481f18b146cSJerin Jacob 	data->dev_link.link_status = ETH_LINK_DOWN;
482f18b146cSJerin Jacob 	data->dev_started = 0;
483f18b146cSJerin Jacob 	data->promiscuous = 0;
484f18b146cSJerin Jacob 	data->all_multicast = 0;
485f18b146cSJerin Jacob 	data->scattered_rx = 0;
486f18b146cSJerin Jacob 
487f18b146cSJerin Jacob 	data->mac_addrs = rte_zmalloc_socket(octtx_name, ETHER_ADDR_LEN, 0,
488f18b146cSJerin Jacob 							socket_id);
489f18b146cSJerin Jacob 	if (data->mac_addrs == NULL) {
490f18b146cSJerin Jacob 		octeontx_log_err("failed to allocate memory for mac_addrs");
491f18b146cSJerin Jacob 		res = -ENOMEM;
492f18b146cSJerin Jacob 		goto err;
493f18b146cSJerin Jacob 	}
494f18b146cSJerin Jacob 
495f18b146cSJerin Jacob 	eth_dev->data = data;
496f18b146cSJerin Jacob 	eth_dev->dev_ops = &octeontx_dev_ops;
497f18b146cSJerin Jacob 
498f18b146cSJerin Jacob 	/* Finally save ethdev pointer to the NIC structure */
499f18b146cSJerin Jacob 	nic->dev = eth_dev;
500f18b146cSJerin Jacob 
501f18b146cSJerin Jacob 	if (nic->port_id != data->port_id) {
502f18b146cSJerin Jacob 		octeontx_log_err("eth_dev->port_id (%d) is diff to orig (%d)",
503f18b146cSJerin Jacob 				data->port_id, nic->port_id);
504f18b146cSJerin Jacob 		res = -EINVAL;
505f18b146cSJerin Jacob 		goto err;
506f18b146cSJerin Jacob 	}
507f18b146cSJerin Jacob 
508f18b146cSJerin Jacob 	/* Update port_id mac to eth_dev */
509f18b146cSJerin Jacob 	memcpy(data->mac_addrs, nic->mac_addr, ETHER_ADDR_LEN);
510f18b146cSJerin Jacob 
511f18b146cSJerin Jacob 	PMD_INIT_LOG(DEBUG, "ethdev info: ");
512f18b146cSJerin Jacob 	PMD_INIT_LOG(DEBUG, "port %d, port_ena %d ochan %d num_ochan %d tx_q %d",
513f18b146cSJerin Jacob 				nic->port_id, nic->port_ena,
514f18b146cSJerin Jacob 				nic->base_ochan, nic->num_ochans,
515f18b146cSJerin Jacob 				nic->num_tx_queues);
516f18b146cSJerin Jacob 	PMD_INIT_LOG(DEBUG, "speed %d mtu %d", nic->speed, nic->mtu);
517f18b146cSJerin Jacob 
518f18b146cSJerin Jacob 	return data->port_id;
519f18b146cSJerin Jacob 
520f18b146cSJerin Jacob err:
521f18b146cSJerin Jacob 	if (port)
522f18b146cSJerin Jacob 		octeontx_port_close(nic);
523f18b146cSJerin Jacob 
524f18b146cSJerin Jacob 	if (eth_dev != NULL) {
525f18b146cSJerin Jacob 		rte_free(eth_dev->data->mac_addrs);
526f18b146cSJerin Jacob 		rte_free(data);
527f18b146cSJerin Jacob 		rte_free(nic);
528f18b146cSJerin Jacob 		rte_eth_dev_release_port(eth_dev);
529f18b146cSJerin Jacob 	}
530f18b146cSJerin Jacob 
531f18b146cSJerin Jacob 	return res;
532f7be70e5SJerin Jacob }
533f7be70e5SJerin Jacob 
534f7be70e5SJerin Jacob /* Un initialize octeontx device */
535f7be70e5SJerin Jacob static int
536f7be70e5SJerin Jacob octeontx_remove(struct rte_vdev_device *dev)
537f7be70e5SJerin Jacob {
538f7be70e5SJerin Jacob 	char octtx_name[OCTEONTX_MAX_NAME_LEN];
539f7be70e5SJerin Jacob 	struct rte_eth_dev *eth_dev = NULL;
540f7be70e5SJerin Jacob 	struct octeontx_nic *nic = NULL;
541f7be70e5SJerin Jacob 	int i;
542f7be70e5SJerin Jacob 
543f7be70e5SJerin Jacob 	if (dev == NULL)
544f7be70e5SJerin Jacob 		return -EINVAL;
545f7be70e5SJerin Jacob 
546f7be70e5SJerin Jacob 	for (i = 0; i < OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT; i++) {
547f7be70e5SJerin Jacob 		sprintf(octtx_name, "eth_octeontx_%d", i);
548f7be70e5SJerin Jacob 
549f7be70e5SJerin Jacob 		/* reserve an ethdev entry */
550f7be70e5SJerin Jacob 		eth_dev = rte_eth_dev_allocated(octtx_name);
551f7be70e5SJerin Jacob 		if (eth_dev == NULL)
552f7be70e5SJerin Jacob 			return -ENODEV;
553f7be70e5SJerin Jacob 
554f7be70e5SJerin Jacob 		nic = octeontx_pmd_priv(eth_dev);
555f7be70e5SJerin Jacob 		rte_event_dev_stop(nic->evdev);
556f7be70e5SJerin Jacob 		PMD_INIT_LOG(INFO, "Closing octeontx device %s", octtx_name);
557f7be70e5SJerin Jacob 
558f7be70e5SJerin Jacob 		rte_free(eth_dev->data->mac_addrs);
559f7be70e5SJerin Jacob 		rte_free(eth_dev->data->dev_private);
560f7be70e5SJerin Jacob 		rte_free(eth_dev->data);
561f7be70e5SJerin Jacob 		rte_eth_dev_release_port(eth_dev);
562f7be70e5SJerin Jacob 		rte_event_dev_close(nic->evdev);
563f7be70e5SJerin Jacob 	}
564f7be70e5SJerin Jacob 
565f7be70e5SJerin Jacob 	/* Free FC resource */
566f7be70e5SJerin Jacob 	octeontx_pko_fc_free();
567f7be70e5SJerin Jacob 
568f7be70e5SJerin Jacob 	return 0;
569f7be70e5SJerin Jacob }
570f7be70e5SJerin Jacob 
571f7be70e5SJerin Jacob /* Initialize octeontx device */
572f7be70e5SJerin Jacob static int
573f7be70e5SJerin Jacob octeontx_probe(struct rte_vdev_device *dev)
574f7be70e5SJerin Jacob {
575f7be70e5SJerin Jacob 	const char *dev_name;
576f7be70e5SJerin Jacob 	static int probe_once;
577f7be70e5SJerin Jacob 	uint8_t socket_id, qlist;
578f7be70e5SJerin Jacob 	int tx_vfcnt, port_id, evdev, qnum, pnum, res, i;
579f7be70e5SJerin Jacob 	struct rte_event_dev_config dev_conf;
580f7be70e5SJerin Jacob 	const char *eventdev_name = "event_octeontx";
581f7be70e5SJerin Jacob 	struct rte_event_dev_info info;
582f7be70e5SJerin Jacob 
583f7be70e5SJerin Jacob 	struct octeontx_vdev_init_params init_params = {
584f7be70e5SJerin Jacob 		OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT
585f7be70e5SJerin Jacob 	};
586f7be70e5SJerin Jacob 
587f7be70e5SJerin Jacob 	dev_name = rte_vdev_device_name(dev);
588f7be70e5SJerin Jacob 	res = octeontx_parse_vdev_init_params(&init_params, dev);
589f7be70e5SJerin Jacob 	if (res < 0)
590f7be70e5SJerin Jacob 		return -EINVAL;
591f7be70e5SJerin Jacob 
592f7be70e5SJerin Jacob 	if (init_params.nr_port > OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT) {
593f7be70e5SJerin Jacob 		octeontx_log_err("nr_port (%d) > max (%d)", init_params.nr_port,
594f7be70e5SJerin Jacob 				OCTEONTX_VDEV_DEFAULT_MAX_NR_PORT);
595f7be70e5SJerin Jacob 		return -ENOTSUP;
596f7be70e5SJerin Jacob 	}
597f7be70e5SJerin Jacob 
598f7be70e5SJerin Jacob 	PMD_INIT_LOG(DEBUG, "initializing %s pmd", dev_name);
599f7be70e5SJerin Jacob 
600f7be70e5SJerin Jacob 	socket_id = rte_socket_id();
601f7be70e5SJerin Jacob 
602f7be70e5SJerin Jacob 	tx_vfcnt = octeontx_pko_vf_count();
603f7be70e5SJerin Jacob 
604f7be70e5SJerin Jacob 	if (tx_vfcnt < init_params.nr_port) {
605f7be70e5SJerin Jacob 		octeontx_log_err("not enough PKO (%d) for port number (%d)",
606f7be70e5SJerin Jacob 				tx_vfcnt, init_params.nr_port);
607f7be70e5SJerin Jacob 		return -EINVAL;
608f7be70e5SJerin Jacob 	}
609f7be70e5SJerin Jacob 	evdev = rte_event_dev_get_dev_id(eventdev_name);
610f7be70e5SJerin Jacob 	if (evdev < 0) {
611f7be70e5SJerin Jacob 		octeontx_log_err("eventdev %s not found", eventdev_name);
612f7be70e5SJerin Jacob 		return -ENODEV;
613f7be70e5SJerin Jacob 	}
614f7be70e5SJerin Jacob 
615f7be70e5SJerin Jacob 	res = rte_event_dev_info_get(evdev, &info);
616f7be70e5SJerin Jacob 	if (res < 0) {
617f7be70e5SJerin Jacob 		octeontx_log_err("failed to eventdev info %d", res);
618f7be70e5SJerin Jacob 		return -EINVAL;
619f7be70e5SJerin Jacob 	}
620f7be70e5SJerin Jacob 
621f7be70e5SJerin Jacob 	PMD_INIT_LOG(DEBUG, "max_queue %d max_port %d",
622f7be70e5SJerin Jacob 			info.max_event_queues, info.max_event_ports);
623f7be70e5SJerin Jacob 
624f7be70e5SJerin Jacob 	if (octeontx_pko_init_fc(tx_vfcnt))
625f7be70e5SJerin Jacob 		return -ENOMEM;
626f7be70e5SJerin Jacob 
627f7be70e5SJerin Jacob 	devconf_set_default_sane_values(&dev_conf, &info);
628f7be70e5SJerin Jacob 	res = rte_event_dev_configure(evdev, &dev_conf);
629f7be70e5SJerin Jacob 	if (res < 0)
630f7be70e5SJerin Jacob 		goto parse_error;
631f7be70e5SJerin Jacob 
632f7be70e5SJerin Jacob 	rte_event_dev_attr_get(evdev, RTE_EVENT_DEV_ATTR_PORT_COUNT,
633f7be70e5SJerin Jacob 			(uint32_t *)&pnum);
634f7be70e5SJerin Jacob 	rte_event_dev_attr_get(evdev, RTE_EVENT_DEV_ATTR_QUEUE_COUNT,
635f7be70e5SJerin Jacob 			(uint32_t *)&qnum);
636f7be70e5SJerin Jacob 	if (pnum < qnum) {
637f7be70e5SJerin Jacob 		octeontx_log_err("too few event ports (%d) for event_q(%d)",
638f7be70e5SJerin Jacob 				pnum, qnum);
639f7be70e5SJerin Jacob 		res = -EINVAL;
640f7be70e5SJerin Jacob 		goto parse_error;
641f7be70e5SJerin Jacob 	}
642f7be70e5SJerin Jacob 	if (pnum > qnum) {
643f7be70e5SJerin Jacob 		/*
644f7be70e5SJerin Jacob 		 * We don't poll on event ports
645f7be70e5SJerin Jacob 		 * that do not have any queues assigned.
646f7be70e5SJerin Jacob 		 */
647f7be70e5SJerin Jacob 		pnum = qnum;
648f7be70e5SJerin Jacob 		PMD_INIT_LOG(INFO,
649f7be70e5SJerin Jacob 			"reducing number of active event ports to %d", pnum);
650f7be70e5SJerin Jacob 	}
651f7be70e5SJerin Jacob 	for (i = 0; i < qnum; i++) {
652f7be70e5SJerin Jacob 		res = rte_event_queue_setup(evdev, i, NULL);
653f7be70e5SJerin Jacob 		if (res < 0) {
654f7be70e5SJerin Jacob 			octeontx_log_err("failed to setup event_q(%d): res %d",
655f7be70e5SJerin Jacob 					i, res);
656f7be70e5SJerin Jacob 			goto parse_error;
657f7be70e5SJerin Jacob 		}
658f7be70e5SJerin Jacob 	}
659f7be70e5SJerin Jacob 
660f7be70e5SJerin Jacob 	for (i = 0; i < pnum; i++) {
661f7be70e5SJerin Jacob 		res = rte_event_port_setup(evdev, i, NULL);
662f7be70e5SJerin Jacob 		if (res < 0) {
663f7be70e5SJerin Jacob 			res = -ENODEV;
664f7be70e5SJerin Jacob 			octeontx_log_err("failed to setup ev port(%d) res=%d",
665f7be70e5SJerin Jacob 						i, res);
666f7be70e5SJerin Jacob 			goto parse_error;
667f7be70e5SJerin Jacob 		}
668f7be70e5SJerin Jacob 		/* Link one queue to one event port */
669f7be70e5SJerin Jacob 		qlist = i;
670f7be70e5SJerin Jacob 		res = rte_event_port_link(evdev, i, &qlist, NULL, 1);
671f7be70e5SJerin Jacob 		if (res < 0) {
672f7be70e5SJerin Jacob 			res = -ENODEV;
673f7be70e5SJerin Jacob 			octeontx_log_err("failed to link port (%d): res=%d",
674f7be70e5SJerin Jacob 					i, res);
675f7be70e5SJerin Jacob 			goto parse_error;
676f7be70e5SJerin Jacob 		}
677f7be70e5SJerin Jacob 	}
678f7be70e5SJerin Jacob 
679f7be70e5SJerin Jacob 	/* Create ethdev interface */
680f7be70e5SJerin Jacob 	for (i = 0; i < init_params.nr_port; i++) {
681f7be70e5SJerin Jacob 		port_id = octeontx_create(dev, i, evdev, socket_id);
682f7be70e5SJerin Jacob 		if (port_id < 0) {
683f7be70e5SJerin Jacob 			octeontx_log_err("failed to create device %s",
684f7be70e5SJerin Jacob 					dev_name);
685f7be70e5SJerin Jacob 			res = -ENODEV;
686f7be70e5SJerin Jacob 			goto parse_error;
687f7be70e5SJerin Jacob 		}
688f7be70e5SJerin Jacob 
689f7be70e5SJerin Jacob 		PMD_INIT_LOG(INFO, "created ethdev %s for port %d", dev_name,
690f7be70e5SJerin Jacob 					port_id);
691f7be70e5SJerin Jacob 	}
692f7be70e5SJerin Jacob 
693f7be70e5SJerin Jacob 	if (probe_once) {
694f7be70e5SJerin Jacob 		octeontx_log_err("interface %s not supported", dev_name);
695f7be70e5SJerin Jacob 		octeontx_remove(dev);
696f7be70e5SJerin Jacob 		res = -ENOTSUP;
697f7be70e5SJerin Jacob 		goto parse_error;
698f7be70e5SJerin Jacob 	}
699f7be70e5SJerin Jacob 	probe_once = 1;
700f7be70e5SJerin Jacob 
701f7be70e5SJerin Jacob 	return 0;
702f7be70e5SJerin Jacob 
703f7be70e5SJerin Jacob parse_error:
704f7be70e5SJerin Jacob 	octeontx_pko_fc_free();
705f7be70e5SJerin Jacob 	return res;
706f7be70e5SJerin Jacob }
707f7be70e5SJerin Jacob 
708f7be70e5SJerin Jacob static struct rte_vdev_driver octeontx_pmd_drv = {
709f7be70e5SJerin Jacob 	.probe = octeontx_probe,
710f7be70e5SJerin Jacob 	.remove = octeontx_remove,
711f7be70e5SJerin Jacob };
712f7be70e5SJerin Jacob 
713f7be70e5SJerin Jacob RTE_PMD_REGISTER_VDEV(OCTEONTX_PMD, octeontx_pmd_drv);
714f7be70e5SJerin Jacob RTE_PMD_REGISTER_ALIAS(OCTEONTX_PMD, eth_octeontx);
715f7be70e5SJerin Jacob RTE_PMD_REGISTER_PARAM_STRING(OCTEONTX_PMD, "nr_port=<int> ");
716