xref: /f-stack/dpdk/drivers/net/enic/enic_ethdev.c (revision 579bf1e2)
1a9643ea8Slogwang /*
2a9643ea8Slogwang  * Copyright 2008-2014 Cisco Systems, Inc.  All rights reserved.
3a9643ea8Slogwang  * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
4a9643ea8Slogwang  *
5a9643ea8Slogwang  * Copyright (c) 2014, Cisco Systems, Inc.
6a9643ea8Slogwang  * All rights reserved.
7a9643ea8Slogwang  *
8a9643ea8Slogwang  * Redistribution and use in source and binary forms, with or without
9a9643ea8Slogwang  * modification, are permitted provided that the following conditions
10a9643ea8Slogwang  * are met:
11a9643ea8Slogwang  *
12a9643ea8Slogwang  * 1. Redistributions of source code must retain the above copyright
13a9643ea8Slogwang  * notice, this list of conditions and the following disclaimer.
14a9643ea8Slogwang  *
15a9643ea8Slogwang  * 2. Redistributions in binary form must reproduce the above copyright
16a9643ea8Slogwang  * notice, this list of conditions and the following disclaimer in
17a9643ea8Slogwang  * the documentation and/or other materials provided with the
18a9643ea8Slogwang  * distribution.
19a9643ea8Slogwang  *
20a9643ea8Slogwang  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21a9643ea8Slogwang  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22a9643ea8Slogwang  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23a9643ea8Slogwang  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24a9643ea8Slogwang  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25a9643ea8Slogwang  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26a9643ea8Slogwang  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27a9643ea8Slogwang  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28a9643ea8Slogwang  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29a9643ea8Slogwang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30a9643ea8Slogwang  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31a9643ea8Slogwang  * POSSIBILITY OF SUCH DAMAGE.
32a9643ea8Slogwang  *
33a9643ea8Slogwang  */
34a9643ea8Slogwang 
35a9643ea8Slogwang #include <stdio.h>
36a9643ea8Slogwang #include <stdint.h>
37a9643ea8Slogwang 
38a9643ea8Slogwang #include <rte_dev.h>
39a9643ea8Slogwang #include <rte_pci.h>
402bfe3f2eSlogwang #include <rte_bus_pci.h>
41a9643ea8Slogwang #include <rte_ethdev.h>
422bfe3f2eSlogwang #include <rte_ethdev_pci.h>
43*579bf1e2Sjfb8856606 #include <rte_kvargs.h>
44a9643ea8Slogwang #include <rte_string_fns.h>
45a9643ea8Slogwang 
46a9643ea8Slogwang #include "vnic_intr.h"
47a9643ea8Slogwang #include "vnic_cq.h"
48a9643ea8Slogwang #include "vnic_wq.h"
49a9643ea8Slogwang #include "vnic_rq.h"
50a9643ea8Slogwang #include "vnic_enet.h"
51a9643ea8Slogwang #include "enic.h"
52a9643ea8Slogwang 
53a9643ea8Slogwang #ifdef RTE_LIBRTE_ENIC_DEBUG
54a9643ea8Slogwang #define ENICPMD_FUNC_TRACE() \
55a9643ea8Slogwang 	RTE_LOG(DEBUG, PMD, "ENICPMD trace: %s\n", __func__)
56a9643ea8Slogwang #else
57a9643ea8Slogwang #define ENICPMD_FUNC_TRACE() (void)0
58a9643ea8Slogwang #endif
59a9643ea8Slogwang 
60a9643ea8Slogwang /*
61a9643ea8Slogwang  * The set of PCI devices this driver supports
62a9643ea8Slogwang  */
63a9643ea8Slogwang #define CISCO_PCI_VENDOR_ID 0x1137
64a9643ea8Slogwang static const struct rte_pci_id pci_id_enic_map[] = {
65a9643ea8Slogwang 	{ RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET) },
66a9643ea8Slogwang 	{ RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) },
67a9643ea8Slogwang 	{.vendor_id = 0, /* sentinel */},
68a9643ea8Slogwang };
69a9643ea8Slogwang 
70*579bf1e2Sjfb8856606 #define ENIC_DEVARG_IG_VLAN_REWRITE "ig-vlan-rewrite"
71*579bf1e2Sjfb8856606 
72a9643ea8Slogwang static int
73a9643ea8Slogwang enicpmd_fdir_ctrl_func(struct rte_eth_dev *eth_dev,
74a9643ea8Slogwang 			enum rte_filter_op filter_op, void *arg)
75a9643ea8Slogwang {
76a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
77a9643ea8Slogwang 	int ret = 0;
78a9643ea8Slogwang 
79a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
80a9643ea8Slogwang 	if (filter_op == RTE_ETH_FILTER_NOP)
81a9643ea8Slogwang 		return 0;
82a9643ea8Slogwang 
83a9643ea8Slogwang 	if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH)
84a9643ea8Slogwang 		return -EINVAL;
85a9643ea8Slogwang 
86a9643ea8Slogwang 	switch (filter_op) {
87a9643ea8Slogwang 	case RTE_ETH_FILTER_ADD:
88a9643ea8Slogwang 	case RTE_ETH_FILTER_UPDATE:
89a9643ea8Slogwang 		ret = enic_fdir_add_fltr(enic,
90a9643ea8Slogwang 			(struct rte_eth_fdir_filter *)arg);
91a9643ea8Slogwang 		break;
92a9643ea8Slogwang 
93a9643ea8Slogwang 	case RTE_ETH_FILTER_DELETE:
94a9643ea8Slogwang 		ret = enic_fdir_del_fltr(enic,
95a9643ea8Slogwang 			(struct rte_eth_fdir_filter *)arg);
96a9643ea8Slogwang 		break;
97a9643ea8Slogwang 
98a9643ea8Slogwang 	case RTE_ETH_FILTER_STATS:
99a9643ea8Slogwang 		enic_fdir_stats_get(enic, (struct rte_eth_fdir_stats *)arg);
100a9643ea8Slogwang 		break;
101a9643ea8Slogwang 
102a9643ea8Slogwang 	case RTE_ETH_FILTER_FLUSH:
103a9643ea8Slogwang 		dev_warning(enic, "unsupported operation %u", filter_op);
104a9643ea8Slogwang 		ret = -ENOTSUP;
105a9643ea8Slogwang 		break;
1062bfe3f2eSlogwang 	case RTE_ETH_FILTER_INFO:
1072bfe3f2eSlogwang 		enic_fdir_info_get(enic, (struct rte_eth_fdir_info *)arg);
1082bfe3f2eSlogwang 		break;
109a9643ea8Slogwang 	default:
110a9643ea8Slogwang 		dev_err(enic, "unknown operation %u", filter_op);
111a9643ea8Slogwang 		ret = -EINVAL;
112a9643ea8Slogwang 		break;
113a9643ea8Slogwang 	}
114a9643ea8Slogwang 	return ret;
115a9643ea8Slogwang }
116a9643ea8Slogwang 
117a9643ea8Slogwang static int
118a9643ea8Slogwang enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev,
119a9643ea8Slogwang 		     enum rte_filter_type filter_type,
120a9643ea8Slogwang 		     enum rte_filter_op filter_op,
121a9643ea8Slogwang 		     void *arg)
122a9643ea8Slogwang {
1232bfe3f2eSlogwang 	int ret = 0;
124a9643ea8Slogwang 
1252bfe3f2eSlogwang 	ENICPMD_FUNC_TRACE();
1262bfe3f2eSlogwang 
1272bfe3f2eSlogwang 	switch (filter_type) {
1282bfe3f2eSlogwang 	case RTE_ETH_FILTER_GENERIC:
1292bfe3f2eSlogwang 		if (filter_op != RTE_ETH_FILTER_GET)
1302bfe3f2eSlogwang 			return -EINVAL;
1312bfe3f2eSlogwang 		*(const void **)arg = &enic_flow_ops;
1322bfe3f2eSlogwang 		break;
1332bfe3f2eSlogwang 	case RTE_ETH_FILTER_FDIR:
134a9643ea8Slogwang 		ret = enicpmd_fdir_ctrl_func(dev, filter_op, arg);
1352bfe3f2eSlogwang 		break;
1362bfe3f2eSlogwang 	default:
137a9643ea8Slogwang 		dev_warning(enic, "Filter type (%d) not supported",
138a9643ea8Slogwang 			filter_type);
1392bfe3f2eSlogwang 		ret = -EINVAL;
1402bfe3f2eSlogwang 		break;
1412bfe3f2eSlogwang 	}
142a9643ea8Slogwang 
143a9643ea8Slogwang 	return ret;
144a9643ea8Slogwang }
145a9643ea8Slogwang 
146a9643ea8Slogwang static void enicpmd_dev_tx_queue_release(void *txq)
147a9643ea8Slogwang {
148a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
1492bfe3f2eSlogwang 
1502bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
1512bfe3f2eSlogwang 		return;
1522bfe3f2eSlogwang 
153a9643ea8Slogwang 	enic_free_wq(txq);
154a9643ea8Slogwang }
155a9643ea8Slogwang 
156a9643ea8Slogwang static int enicpmd_dev_setup_intr(struct enic *enic)
157a9643ea8Slogwang {
158a9643ea8Slogwang 	int ret;
159a9643ea8Slogwang 	unsigned int index;
160a9643ea8Slogwang 
161a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
162a9643ea8Slogwang 
163a9643ea8Slogwang 	/* Are we done with the init of all the queues? */
164a9643ea8Slogwang 	for (index = 0; index < enic->cq_count; index++) {
165a9643ea8Slogwang 		if (!enic->cq[index].ctrl)
166a9643ea8Slogwang 			break;
167a9643ea8Slogwang 	}
168a9643ea8Slogwang 	if (enic->cq_count != index)
169a9643ea8Slogwang 		return 0;
170a9643ea8Slogwang 	for (index = 0; index < enic->wq_count; index++) {
171a9643ea8Slogwang 		if (!enic->wq[index].ctrl)
172a9643ea8Slogwang 			break;
173a9643ea8Slogwang 	}
174a9643ea8Slogwang 	if (enic->wq_count != index)
175a9643ea8Slogwang 		return 0;
176a9643ea8Slogwang 	/* check start of packet (SOP) RQs only in case scatter is disabled. */
177a9643ea8Slogwang 	for (index = 0; index < enic->rq_count; index++) {
1782bfe3f2eSlogwang 		if (!enic->rq[enic_rte_rq_idx_to_sop_idx(index)].ctrl)
179a9643ea8Slogwang 			break;
180a9643ea8Slogwang 	}
181a9643ea8Slogwang 	if (enic->rq_count != index)
182a9643ea8Slogwang 		return 0;
183a9643ea8Slogwang 
184a9643ea8Slogwang 	ret = enic_alloc_intr_resources(enic);
185a9643ea8Slogwang 	if (ret) {
186a9643ea8Slogwang 		dev_err(enic, "alloc intr failed\n");
187a9643ea8Slogwang 		return ret;
188a9643ea8Slogwang 	}
189a9643ea8Slogwang 	enic_init_vnic_resources(enic);
190a9643ea8Slogwang 
191a9643ea8Slogwang 	ret = enic_setup_finish(enic);
192a9643ea8Slogwang 	if (ret)
193a9643ea8Slogwang 		dev_err(enic, "setup could not be finished\n");
194a9643ea8Slogwang 
195a9643ea8Slogwang 	return ret;
196a9643ea8Slogwang }
197a9643ea8Slogwang 
198a9643ea8Slogwang static int enicpmd_dev_tx_queue_setup(struct rte_eth_dev *eth_dev,
199a9643ea8Slogwang 	uint16_t queue_idx,
200a9643ea8Slogwang 	uint16_t nb_desc,
201a9643ea8Slogwang 	unsigned int socket_id,
202a9643ea8Slogwang 	__rte_unused const struct rte_eth_txconf *tx_conf)
203a9643ea8Slogwang {
204a9643ea8Slogwang 	int ret;
205a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
206a9643ea8Slogwang 
2072bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
2082bfe3f2eSlogwang 		return -E_RTE_SECONDARY;
209a9643ea8Slogwang 
2102bfe3f2eSlogwang 	ENICPMD_FUNC_TRACE();
2112bfe3f2eSlogwang 	RTE_ASSERT(queue_idx < enic->conf_wq_count);
212a9643ea8Slogwang 	eth_dev->data->tx_queues[queue_idx] = (void *)&enic->wq[queue_idx];
213a9643ea8Slogwang 
214a9643ea8Slogwang 	ret = enic_alloc_wq(enic, queue_idx, socket_id, nb_desc);
215a9643ea8Slogwang 	if (ret) {
216a9643ea8Slogwang 		dev_err(enic, "error in allocating wq\n");
217a9643ea8Slogwang 		return ret;
218a9643ea8Slogwang 	}
219a9643ea8Slogwang 
220a9643ea8Slogwang 	return enicpmd_dev_setup_intr(enic);
221a9643ea8Slogwang }
222a9643ea8Slogwang 
223a9643ea8Slogwang static int enicpmd_dev_tx_queue_start(struct rte_eth_dev *eth_dev,
224a9643ea8Slogwang 	uint16_t queue_idx)
225a9643ea8Slogwang {
226a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
227a9643ea8Slogwang 
228a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
229a9643ea8Slogwang 
230a9643ea8Slogwang 	enic_start_wq(enic, queue_idx);
231a9643ea8Slogwang 
232a9643ea8Slogwang 	return 0;
233a9643ea8Slogwang }
234a9643ea8Slogwang 
235a9643ea8Slogwang static int enicpmd_dev_tx_queue_stop(struct rte_eth_dev *eth_dev,
236a9643ea8Slogwang 	uint16_t queue_idx)
237a9643ea8Slogwang {
238a9643ea8Slogwang 	int ret;
239a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
240a9643ea8Slogwang 
241a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
242a9643ea8Slogwang 
243a9643ea8Slogwang 	ret = enic_stop_wq(enic, queue_idx);
244a9643ea8Slogwang 	if (ret)
245a9643ea8Slogwang 		dev_err(enic, "error in stopping wq %d\n", queue_idx);
246a9643ea8Slogwang 
247a9643ea8Slogwang 	return ret;
248a9643ea8Slogwang }
249a9643ea8Slogwang 
250a9643ea8Slogwang static int enicpmd_dev_rx_queue_start(struct rte_eth_dev *eth_dev,
251a9643ea8Slogwang 	uint16_t queue_idx)
252a9643ea8Slogwang {
253a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
254a9643ea8Slogwang 
255a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
256a9643ea8Slogwang 
257a9643ea8Slogwang 	enic_start_rq(enic, queue_idx);
258a9643ea8Slogwang 
259a9643ea8Slogwang 	return 0;
260a9643ea8Slogwang }
261a9643ea8Slogwang 
262a9643ea8Slogwang static int enicpmd_dev_rx_queue_stop(struct rte_eth_dev *eth_dev,
263a9643ea8Slogwang 	uint16_t queue_idx)
264a9643ea8Slogwang {
265a9643ea8Slogwang 	int ret;
266a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
267a9643ea8Slogwang 
268a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
269a9643ea8Slogwang 
270a9643ea8Slogwang 	ret = enic_stop_rq(enic, queue_idx);
271a9643ea8Slogwang 	if (ret)
272a9643ea8Slogwang 		dev_err(enic, "error in stopping rq %d\n", queue_idx);
273a9643ea8Slogwang 
274a9643ea8Slogwang 	return ret;
275a9643ea8Slogwang }
276a9643ea8Slogwang 
277a9643ea8Slogwang static void enicpmd_dev_rx_queue_release(void *rxq)
278a9643ea8Slogwang {
279a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
2802bfe3f2eSlogwang 
2812bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
2822bfe3f2eSlogwang 		return;
2832bfe3f2eSlogwang 
284a9643ea8Slogwang 	enic_free_rq(rxq);
285a9643ea8Slogwang }
286a9643ea8Slogwang 
2872bfe3f2eSlogwang static uint32_t enicpmd_dev_rx_queue_count(struct rte_eth_dev *dev,
2882bfe3f2eSlogwang 					   uint16_t rx_queue_id)
2892bfe3f2eSlogwang {
2902bfe3f2eSlogwang 	struct enic *enic = pmd_priv(dev);
2912bfe3f2eSlogwang 	uint32_t queue_count = 0;
2922bfe3f2eSlogwang 	struct vnic_cq *cq;
2932bfe3f2eSlogwang 	uint32_t cq_tail;
2942bfe3f2eSlogwang 	uint16_t cq_idx;
2952bfe3f2eSlogwang 	int rq_num;
2962bfe3f2eSlogwang 
2972bfe3f2eSlogwang 	rq_num = enic_rte_rq_idx_to_sop_idx(rx_queue_id);
2982bfe3f2eSlogwang 	cq = &enic->cq[enic_cq_rq(enic, rq_num)];
2992bfe3f2eSlogwang 	cq_idx = cq->to_clean;
3002bfe3f2eSlogwang 
3012bfe3f2eSlogwang 	cq_tail = ioread32(&cq->ctrl->cq_tail);
3022bfe3f2eSlogwang 
3032bfe3f2eSlogwang 	if (cq_tail < cq_idx)
3042bfe3f2eSlogwang 		cq_tail += cq->ring.desc_count;
3052bfe3f2eSlogwang 
3062bfe3f2eSlogwang 	queue_count = cq_tail - cq_idx;
3072bfe3f2eSlogwang 
3082bfe3f2eSlogwang 	return queue_count;
3092bfe3f2eSlogwang }
3102bfe3f2eSlogwang 
311a9643ea8Slogwang static int enicpmd_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
312a9643ea8Slogwang 	uint16_t queue_idx,
313a9643ea8Slogwang 	uint16_t nb_desc,
314a9643ea8Slogwang 	unsigned int socket_id,
315a9643ea8Slogwang 	const struct rte_eth_rxconf *rx_conf,
316a9643ea8Slogwang 	struct rte_mempool *mp)
317a9643ea8Slogwang {
318a9643ea8Slogwang 	int ret;
319a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
320a9643ea8Slogwang 
321a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
322a9643ea8Slogwang 
3232bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
3242bfe3f2eSlogwang 		return -E_RTE_SECONDARY;
3252bfe3f2eSlogwang 	RTE_ASSERT(enic_rte_rq_idx_to_sop_idx(queue_idx) < enic->conf_rq_count);
326a9643ea8Slogwang 	eth_dev->data->rx_queues[queue_idx] =
3272bfe3f2eSlogwang 		(void *)&enic->rq[enic_rte_rq_idx_to_sop_idx(queue_idx)];
328a9643ea8Slogwang 
329a9643ea8Slogwang 	ret = enic_alloc_rq(enic, queue_idx, socket_id, mp, nb_desc,
330a9643ea8Slogwang 			    rx_conf->rx_free_thresh);
331a9643ea8Slogwang 	if (ret) {
332a9643ea8Slogwang 		dev_err(enic, "error in allocating rq\n");
333a9643ea8Slogwang 		return ret;
334a9643ea8Slogwang 	}
335a9643ea8Slogwang 
336a9643ea8Slogwang 	return enicpmd_dev_setup_intr(enic);
337a9643ea8Slogwang }
338a9643ea8Slogwang 
339a9643ea8Slogwang static int enicpmd_vlan_filter_set(struct rte_eth_dev *eth_dev,
340a9643ea8Slogwang 	uint16_t vlan_id, int on)
341a9643ea8Slogwang {
342a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
343a9643ea8Slogwang 	int err;
344a9643ea8Slogwang 
345a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
346a9643ea8Slogwang 	if (on)
347a9643ea8Slogwang 		err = enic_add_vlan(enic, vlan_id);
348a9643ea8Slogwang 	else
349a9643ea8Slogwang 		err = enic_del_vlan(enic, vlan_id);
350a9643ea8Slogwang 	return err;
351a9643ea8Slogwang }
352a9643ea8Slogwang 
3532bfe3f2eSlogwang static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
354a9643ea8Slogwang {
355a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
356a9643ea8Slogwang 
357a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
358a9643ea8Slogwang 
359a9643ea8Slogwang 	if (mask & ETH_VLAN_STRIP_MASK) {
360a9643ea8Slogwang 		if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip)
361a9643ea8Slogwang 			enic->ig_vlan_strip_en = 1;
362a9643ea8Slogwang 		else
363a9643ea8Slogwang 			enic->ig_vlan_strip_en = 0;
364a9643ea8Slogwang 	}
365a9643ea8Slogwang 	enic_set_rss_nic_cfg(enic);
366a9643ea8Slogwang 
367a9643ea8Slogwang 
368a9643ea8Slogwang 	if (mask & ETH_VLAN_FILTER_MASK) {
369a9643ea8Slogwang 		dev_warning(enic,
370a9643ea8Slogwang 			"Configuration of VLAN filter is not supported\n");
371a9643ea8Slogwang 	}
372a9643ea8Slogwang 
373a9643ea8Slogwang 	if (mask & ETH_VLAN_EXTEND_MASK) {
374a9643ea8Slogwang 		dev_warning(enic,
375a9643ea8Slogwang 			"Configuration of extended VLAN is not supported\n");
376a9643ea8Slogwang 	}
3772bfe3f2eSlogwang 
3782bfe3f2eSlogwang 	return 0;
379a9643ea8Slogwang }
380a9643ea8Slogwang 
381a9643ea8Slogwang static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
382a9643ea8Slogwang {
383a9643ea8Slogwang 	int ret;
384a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
385a9643ea8Slogwang 
3862bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
3872bfe3f2eSlogwang 		return -E_RTE_SECONDARY;
3882bfe3f2eSlogwang 
389a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
390a9643ea8Slogwang 	ret = enic_set_vnic_res(enic);
391a9643ea8Slogwang 	if (ret) {
392a9643ea8Slogwang 		dev_err(enic, "Set vNIC resource num  failed, aborting\n");
393a9643ea8Slogwang 		return ret;
394a9643ea8Slogwang 	}
395a9643ea8Slogwang 
396a9643ea8Slogwang 	if (eth_dev->data->dev_conf.rxmode.split_hdr_size &&
397a9643ea8Slogwang 		eth_dev->data->dev_conf.rxmode.header_split) {
398a9643ea8Slogwang 		/* Enable header-data-split */
399a9643ea8Slogwang 		enic_set_hdr_split_size(enic,
400a9643ea8Slogwang 			eth_dev->data->dev_conf.rxmode.split_hdr_size);
401a9643ea8Slogwang 	}
402a9643ea8Slogwang 
403a9643ea8Slogwang 	enic->hw_ip_checksum = eth_dev->data->dev_conf.rxmode.hw_ip_checksum;
4042bfe3f2eSlogwang 	ret = enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
4052bfe3f2eSlogwang 
4062bfe3f2eSlogwang 	return ret;
407a9643ea8Slogwang }
408a9643ea8Slogwang 
409a9643ea8Slogwang /* Start the device.
410a9643ea8Slogwang  * It returns 0 on success.
411a9643ea8Slogwang  */
412a9643ea8Slogwang static int enicpmd_dev_start(struct rte_eth_dev *eth_dev)
413a9643ea8Slogwang {
414a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
415a9643ea8Slogwang 
4162bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
4172bfe3f2eSlogwang 		return -E_RTE_SECONDARY;
4182bfe3f2eSlogwang 
419a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
420a9643ea8Slogwang 	return enic_enable(enic);
421a9643ea8Slogwang }
422a9643ea8Slogwang 
423a9643ea8Slogwang /*
424a9643ea8Slogwang  * Stop device: disable rx and tx functions to allow for reconfiguring.
425a9643ea8Slogwang  */
426a9643ea8Slogwang static void enicpmd_dev_stop(struct rte_eth_dev *eth_dev)
427a9643ea8Slogwang {
428a9643ea8Slogwang 	struct rte_eth_link link;
429a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
430a9643ea8Slogwang 
4312bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
4322bfe3f2eSlogwang 		return;
4332bfe3f2eSlogwang 
434a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
435a9643ea8Slogwang 	enic_disable(enic);
436a9643ea8Slogwang 	memset(&link, 0, sizeof(link));
437a9643ea8Slogwang 	rte_atomic64_cmpset((uint64_t *)&eth_dev->data->dev_link,
438a9643ea8Slogwang 		*(uint64_t *)&eth_dev->data->dev_link,
439a9643ea8Slogwang 		*(uint64_t *)&link);
440a9643ea8Slogwang }
441a9643ea8Slogwang 
442a9643ea8Slogwang /*
443a9643ea8Slogwang  * Stop device.
444a9643ea8Slogwang  */
445a9643ea8Slogwang static void enicpmd_dev_close(struct rte_eth_dev *eth_dev)
446a9643ea8Slogwang {
447a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
448a9643ea8Slogwang 
449a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
450a9643ea8Slogwang 	enic_remove(enic);
451a9643ea8Slogwang }
452a9643ea8Slogwang 
453a9643ea8Slogwang static int enicpmd_dev_link_update(struct rte_eth_dev *eth_dev,
454a9643ea8Slogwang 	__rte_unused int wait_to_complete)
455a9643ea8Slogwang {
456a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
457a9643ea8Slogwang 
458a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
4592bfe3f2eSlogwang 	return enic_link_update(enic);
460a9643ea8Slogwang }
461a9643ea8Slogwang 
4622bfe3f2eSlogwang static int enicpmd_dev_stats_get(struct rte_eth_dev *eth_dev,
463a9643ea8Slogwang 	struct rte_eth_stats *stats)
464a9643ea8Slogwang {
465a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
466a9643ea8Slogwang 
467a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
4682bfe3f2eSlogwang 	return enic_dev_stats_get(enic, stats);
469a9643ea8Slogwang }
470a9643ea8Slogwang 
471a9643ea8Slogwang static void enicpmd_dev_stats_reset(struct rte_eth_dev *eth_dev)
472a9643ea8Slogwang {
473a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
474a9643ea8Slogwang 
475a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
476a9643ea8Slogwang 	enic_dev_stats_clear(enic);
477a9643ea8Slogwang }
478a9643ea8Slogwang 
479a9643ea8Slogwang static void enicpmd_dev_info_get(struct rte_eth_dev *eth_dev,
480a9643ea8Slogwang 	struct rte_eth_dev_info *device_info)
481a9643ea8Slogwang {
482a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
483a9643ea8Slogwang 
484a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
4852bfe3f2eSlogwang 	device_info->pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
486a9643ea8Slogwang 	/* Scattered Rx uses two receive queues per rx queue exposed to dpdk */
487a9643ea8Slogwang 	device_info->max_rx_queues = enic->conf_rq_count / 2;
488a9643ea8Slogwang 	device_info->max_tx_queues = enic->conf_wq_count;
489a9643ea8Slogwang 	device_info->min_rx_bufsize = ENIC_MIN_MTU;
490a9643ea8Slogwang 	device_info->max_rx_pktlen = enic->max_mtu + ETHER_HDR_LEN + 4;
4912bfe3f2eSlogwang 	device_info->max_mac_addrs = ENIC_MAX_MAC_ADDR;
492a9643ea8Slogwang 	device_info->rx_offload_capa =
493a9643ea8Slogwang 		DEV_RX_OFFLOAD_VLAN_STRIP |
494a9643ea8Slogwang 		DEV_RX_OFFLOAD_IPV4_CKSUM |
495a9643ea8Slogwang 		DEV_RX_OFFLOAD_UDP_CKSUM  |
496a9643ea8Slogwang 		DEV_RX_OFFLOAD_TCP_CKSUM;
497a9643ea8Slogwang 	device_info->tx_offload_capa =
498a9643ea8Slogwang 		DEV_TX_OFFLOAD_VLAN_INSERT |
499a9643ea8Slogwang 		DEV_TX_OFFLOAD_IPV4_CKSUM  |
500a9643ea8Slogwang 		DEV_TX_OFFLOAD_UDP_CKSUM   |
5012bfe3f2eSlogwang 		DEV_TX_OFFLOAD_TCP_CKSUM   |
5022bfe3f2eSlogwang 		DEV_TX_OFFLOAD_TCP_TSO;
503a9643ea8Slogwang 	device_info->default_rxconf = (struct rte_eth_rxconf) {
504a9643ea8Slogwang 		.rx_free_thresh = ENIC_DEFAULT_RX_FREE_THRESH
505a9643ea8Slogwang 	};
506a9643ea8Slogwang }
507a9643ea8Slogwang 
508a9643ea8Slogwang static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev)
509a9643ea8Slogwang {
510a9643ea8Slogwang 	static const uint32_t ptypes[] = {
5112bfe3f2eSlogwang 		RTE_PTYPE_L2_ETHER,
5122bfe3f2eSlogwang 		RTE_PTYPE_L2_ETHER_VLAN,
513a9643ea8Slogwang 		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
514a9643ea8Slogwang 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
515a9643ea8Slogwang 		RTE_PTYPE_L4_TCP,
516a9643ea8Slogwang 		RTE_PTYPE_L4_UDP,
517a9643ea8Slogwang 		RTE_PTYPE_L4_FRAG,
518a9643ea8Slogwang 		RTE_PTYPE_L4_NONFRAG,
519a9643ea8Slogwang 		RTE_PTYPE_UNKNOWN
520a9643ea8Slogwang 	};
521a9643ea8Slogwang 
522a9643ea8Slogwang 	if (dev->rx_pkt_burst == enic_recv_pkts)
523a9643ea8Slogwang 		return ptypes;
524a9643ea8Slogwang 	return NULL;
525a9643ea8Slogwang }
526a9643ea8Slogwang 
527a9643ea8Slogwang static void enicpmd_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
528a9643ea8Slogwang {
529a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
530a9643ea8Slogwang 
5312bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
5322bfe3f2eSlogwang 		return;
5332bfe3f2eSlogwang 
534a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
5352bfe3f2eSlogwang 
536a9643ea8Slogwang 	enic->promisc = 1;
537a9643ea8Slogwang 	enic_add_packet_filter(enic);
538a9643ea8Slogwang }
539a9643ea8Slogwang 
540a9643ea8Slogwang static void enicpmd_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
541a9643ea8Slogwang {
542a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
543a9643ea8Slogwang 
5442bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
5452bfe3f2eSlogwang 		return;
5462bfe3f2eSlogwang 
547a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
548a9643ea8Slogwang 	enic->promisc = 0;
549a9643ea8Slogwang 	enic_add_packet_filter(enic);
550a9643ea8Slogwang }
551a9643ea8Slogwang 
552a9643ea8Slogwang static void enicpmd_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
553a9643ea8Slogwang {
554a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
555a9643ea8Slogwang 
5562bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
5572bfe3f2eSlogwang 		return;
5582bfe3f2eSlogwang 
559a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
560a9643ea8Slogwang 	enic->allmulti = 1;
561a9643ea8Slogwang 	enic_add_packet_filter(enic);
562a9643ea8Slogwang }
563a9643ea8Slogwang 
564a9643ea8Slogwang static void enicpmd_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
565a9643ea8Slogwang {
566a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
567a9643ea8Slogwang 
5682bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
5692bfe3f2eSlogwang 		return;
5702bfe3f2eSlogwang 
571a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
572a9643ea8Slogwang 	enic->allmulti = 0;
573a9643ea8Slogwang 	enic_add_packet_filter(enic);
574a9643ea8Slogwang }
575a9643ea8Slogwang 
5762bfe3f2eSlogwang static int enicpmd_add_mac_addr(struct rte_eth_dev *eth_dev,
577a9643ea8Slogwang 	struct ether_addr *mac_addr,
578a9643ea8Slogwang 	__rte_unused uint32_t index, __rte_unused uint32_t pool)
579a9643ea8Slogwang {
580a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
581a9643ea8Slogwang 
5822bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
5832bfe3f2eSlogwang 		return -E_RTE_SECONDARY;
5842bfe3f2eSlogwang 
585a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
5862bfe3f2eSlogwang 	return enic_set_mac_address(enic, mac_addr->addr_bytes);
587a9643ea8Slogwang }
588a9643ea8Slogwang 
5892bfe3f2eSlogwang static void enicpmd_remove_mac_addr(struct rte_eth_dev *eth_dev, uint32_t index)
590a9643ea8Slogwang {
591a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
592a9643ea8Slogwang 
5932bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
5942bfe3f2eSlogwang 		return;
5952bfe3f2eSlogwang 
596a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
5972bfe3f2eSlogwang 	enic_del_mac_address(enic, index);
598a9643ea8Slogwang }
599a9643ea8Slogwang 
600a9643ea8Slogwang static int enicpmd_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
601a9643ea8Slogwang {
602a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
603a9643ea8Slogwang 
604a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
605a9643ea8Slogwang 	return enic_set_mtu(enic, mtu);
606a9643ea8Slogwang }
607a9643ea8Slogwang 
608a9643ea8Slogwang static const struct eth_dev_ops enicpmd_eth_dev_ops = {
609a9643ea8Slogwang 	.dev_configure        = enicpmd_dev_configure,
610a9643ea8Slogwang 	.dev_start            = enicpmd_dev_start,
611a9643ea8Slogwang 	.dev_stop             = enicpmd_dev_stop,
612a9643ea8Slogwang 	.dev_set_link_up      = NULL,
613a9643ea8Slogwang 	.dev_set_link_down    = NULL,
614a9643ea8Slogwang 	.dev_close            = enicpmd_dev_close,
615a9643ea8Slogwang 	.promiscuous_enable   = enicpmd_dev_promiscuous_enable,
616a9643ea8Slogwang 	.promiscuous_disable  = enicpmd_dev_promiscuous_disable,
617a9643ea8Slogwang 	.allmulticast_enable  = enicpmd_dev_allmulticast_enable,
618a9643ea8Slogwang 	.allmulticast_disable = enicpmd_dev_allmulticast_disable,
619a9643ea8Slogwang 	.link_update          = enicpmd_dev_link_update,
620a9643ea8Slogwang 	.stats_get            = enicpmd_dev_stats_get,
621a9643ea8Slogwang 	.stats_reset          = enicpmd_dev_stats_reset,
622a9643ea8Slogwang 	.queue_stats_mapping_set = NULL,
623a9643ea8Slogwang 	.dev_infos_get        = enicpmd_dev_info_get,
624a9643ea8Slogwang 	.dev_supported_ptypes_get = enicpmd_dev_supported_ptypes_get,
625a9643ea8Slogwang 	.mtu_set              = enicpmd_mtu_set,
626a9643ea8Slogwang 	.vlan_filter_set      = enicpmd_vlan_filter_set,
627a9643ea8Slogwang 	.vlan_tpid_set        = NULL,
628a9643ea8Slogwang 	.vlan_offload_set     = enicpmd_vlan_offload_set,
629a9643ea8Slogwang 	.vlan_strip_queue_set = NULL,
630a9643ea8Slogwang 	.rx_queue_start       = enicpmd_dev_rx_queue_start,
631a9643ea8Slogwang 	.rx_queue_stop        = enicpmd_dev_rx_queue_stop,
632a9643ea8Slogwang 	.tx_queue_start       = enicpmd_dev_tx_queue_start,
633a9643ea8Slogwang 	.tx_queue_stop        = enicpmd_dev_tx_queue_stop,
634a9643ea8Slogwang 	.rx_queue_setup       = enicpmd_dev_rx_queue_setup,
635a9643ea8Slogwang 	.rx_queue_release     = enicpmd_dev_rx_queue_release,
6362bfe3f2eSlogwang 	.rx_queue_count       = enicpmd_dev_rx_queue_count,
637a9643ea8Slogwang 	.rx_descriptor_done   = NULL,
638a9643ea8Slogwang 	.tx_queue_setup       = enicpmd_dev_tx_queue_setup,
639a9643ea8Slogwang 	.tx_queue_release     = enicpmd_dev_tx_queue_release,
640a9643ea8Slogwang 	.dev_led_on           = NULL,
641a9643ea8Slogwang 	.dev_led_off          = NULL,
642a9643ea8Slogwang 	.flow_ctrl_get        = NULL,
643a9643ea8Slogwang 	.flow_ctrl_set        = NULL,
644a9643ea8Slogwang 	.priority_flow_ctrl_set = NULL,
645a9643ea8Slogwang 	.mac_addr_add         = enicpmd_add_mac_addr,
646a9643ea8Slogwang 	.mac_addr_remove      = enicpmd_remove_mac_addr,
647a9643ea8Slogwang 	.filter_ctrl          = enicpmd_dev_filter_ctrl,
648a9643ea8Slogwang };
649a9643ea8Slogwang 
650*579bf1e2Sjfb8856606 static int enic_parse_ig_vlan_rewrite(__rte_unused const char *key,
651*579bf1e2Sjfb8856606 				      const char *value,
652*579bf1e2Sjfb8856606 				      void *opaque)
653*579bf1e2Sjfb8856606 {
654*579bf1e2Sjfb8856606 	struct enic *enic;
655*579bf1e2Sjfb8856606 
656*579bf1e2Sjfb8856606 	enic = (struct enic *)opaque;
657*579bf1e2Sjfb8856606 	if (strcmp(value, "trunk") == 0) {
658*579bf1e2Sjfb8856606 		/* Trunk mode: always tag */
659*579bf1e2Sjfb8856606 		enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_DEFAULT_TRUNK;
660*579bf1e2Sjfb8856606 	} else if (strcmp(value, "untag") == 0) {
661*579bf1e2Sjfb8856606 		/* Untag default VLAN mode: untag if VLAN = default VLAN */
662*579bf1e2Sjfb8856606 		enic->ig_vlan_rewrite_mode =
663*579bf1e2Sjfb8856606 			IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN;
664*579bf1e2Sjfb8856606 	} else if (strcmp(value, "priority") == 0) {
665*579bf1e2Sjfb8856606 		/*
666*579bf1e2Sjfb8856606 		 * Priority-tag default VLAN mode: priority tag (VLAN header
667*579bf1e2Sjfb8856606 		 * with ID=0) if VLAN = default
668*579bf1e2Sjfb8856606 		 */
669*579bf1e2Sjfb8856606 		enic->ig_vlan_rewrite_mode =
670*579bf1e2Sjfb8856606 			IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN;
671*579bf1e2Sjfb8856606 	} else if (strcmp(value, "pass") == 0) {
672*579bf1e2Sjfb8856606 		/* Pass through mode: do not touch tags */
673*579bf1e2Sjfb8856606 		enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_PASS_THRU;
674*579bf1e2Sjfb8856606 	} else {
675*579bf1e2Sjfb8856606 		dev_err(enic, "Invalid value for " ENIC_DEVARG_IG_VLAN_REWRITE
676*579bf1e2Sjfb8856606 			": expected=trunk|untag|priority|pass given=%s\n",
677*579bf1e2Sjfb8856606 			value);
678*579bf1e2Sjfb8856606 		return -EINVAL;
679*579bf1e2Sjfb8856606 	}
680*579bf1e2Sjfb8856606 	return 0;
681*579bf1e2Sjfb8856606 }
682*579bf1e2Sjfb8856606 
683*579bf1e2Sjfb8856606 static int enic_check_devargs(struct rte_eth_dev *dev)
684*579bf1e2Sjfb8856606 {
685*579bf1e2Sjfb8856606 	static const char *const valid_keys[] = {
686*579bf1e2Sjfb8856606 		ENIC_DEVARG_IG_VLAN_REWRITE,
687*579bf1e2Sjfb8856606 		NULL};
688*579bf1e2Sjfb8856606 	struct enic *enic = pmd_priv(dev);
689*579bf1e2Sjfb8856606 	struct rte_kvargs *kvlist;
690*579bf1e2Sjfb8856606 
691*579bf1e2Sjfb8856606 	ENICPMD_FUNC_TRACE();
692*579bf1e2Sjfb8856606 
693*579bf1e2Sjfb8856606 	enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_PASS_THRU;
694*579bf1e2Sjfb8856606 	if (!dev->device->devargs)
695*579bf1e2Sjfb8856606 		return 0;
696*579bf1e2Sjfb8856606 	kvlist = rte_kvargs_parse(dev->device->devargs->args, valid_keys);
697*579bf1e2Sjfb8856606 	if (!kvlist)
698*579bf1e2Sjfb8856606 		return -EINVAL;
699*579bf1e2Sjfb8856606 	if (rte_kvargs_process(kvlist, ENIC_DEVARG_IG_VLAN_REWRITE,
700*579bf1e2Sjfb8856606 			       enic_parse_ig_vlan_rewrite, enic) < 0) {
701*579bf1e2Sjfb8856606 		rte_kvargs_free(kvlist);
702*579bf1e2Sjfb8856606 		return -EINVAL;
703*579bf1e2Sjfb8856606 	}
704*579bf1e2Sjfb8856606 	rte_kvargs_free(kvlist);
705*579bf1e2Sjfb8856606 	return 0;
706*579bf1e2Sjfb8856606 }
707*579bf1e2Sjfb8856606 
708a9643ea8Slogwang struct enic *enicpmd_list_head = NULL;
709a9643ea8Slogwang /* Initialize the driver
710a9643ea8Slogwang  * It returns 0 on success.
711a9643ea8Slogwang  */
712a9643ea8Slogwang static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev)
713a9643ea8Slogwang {
714a9643ea8Slogwang 	struct rte_pci_device *pdev;
715a9643ea8Slogwang 	struct rte_pci_addr *addr;
716a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
717*579bf1e2Sjfb8856606 	int err;
718a9643ea8Slogwang 
719a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
720a9643ea8Slogwang 
721a9643ea8Slogwang 	enic->port_id = eth_dev->data->port_id;
722a9643ea8Slogwang 	enic->rte_dev = eth_dev;
723a9643ea8Slogwang 	eth_dev->dev_ops = &enicpmd_eth_dev_ops;
724a9643ea8Slogwang 	eth_dev->rx_pkt_burst = &enic_recv_pkts;
725a9643ea8Slogwang 	eth_dev->tx_pkt_burst = &enic_xmit_pkts;
726a9643ea8Slogwang 
7272bfe3f2eSlogwang 	pdev = RTE_ETH_DEV_TO_PCI(eth_dev);
728a9643ea8Slogwang 	rte_eth_copy_pci_info(eth_dev, pdev);
729a9643ea8Slogwang 	enic->pdev = pdev;
730a9643ea8Slogwang 	addr = &pdev->addr;
731a9643ea8Slogwang 
732a9643ea8Slogwang 	snprintf(enic->bdf_name, ENICPMD_BDF_LENGTH, "%04x:%02x:%02x.%x",
733a9643ea8Slogwang 		addr->domain, addr->bus, addr->devid, addr->function);
734a9643ea8Slogwang 
735*579bf1e2Sjfb8856606 	err = enic_check_devargs(eth_dev);
736*579bf1e2Sjfb8856606 	if (err)
737*579bf1e2Sjfb8856606 		return err;
738a9643ea8Slogwang 	return enic_probe(enic);
739a9643ea8Slogwang }
740a9643ea8Slogwang 
7412bfe3f2eSlogwang static int eth_enic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
7422bfe3f2eSlogwang 	struct rte_pci_device *pci_dev)
743a9643ea8Slogwang {
7442bfe3f2eSlogwang 	return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct enic),
7452bfe3f2eSlogwang 		eth_enicpmd_dev_init);
746a9643ea8Slogwang }
747a9643ea8Slogwang 
7482bfe3f2eSlogwang static int eth_enic_pci_remove(struct rte_pci_device *pci_dev)
7492bfe3f2eSlogwang {
7502bfe3f2eSlogwang 	return rte_eth_dev_pci_generic_remove(pci_dev, NULL);
7512bfe3f2eSlogwang }
7522bfe3f2eSlogwang 
7532bfe3f2eSlogwang static struct rte_pci_driver rte_enic_pmd = {
7542bfe3f2eSlogwang 	.id_table = pci_id_enic_map,
7552bfe3f2eSlogwang 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
7562bfe3f2eSlogwang 	.probe = eth_enic_pci_probe,
7572bfe3f2eSlogwang 	.remove = eth_enic_pci_remove,
758a9643ea8Slogwang };
759a9643ea8Slogwang 
7602bfe3f2eSlogwang RTE_PMD_REGISTER_PCI(net_enic, rte_enic_pmd);
7612bfe3f2eSlogwang RTE_PMD_REGISTER_PCI_TABLE(net_enic, pci_id_enic_map);
7622bfe3f2eSlogwang RTE_PMD_REGISTER_KMOD_DEP(net_enic, "* igb_uio | uio_pci_generic | vfio-pci");
763*579bf1e2Sjfb8856606 RTE_PMD_REGISTER_PARAM_STRING(net_enic,
764*579bf1e2Sjfb8856606 	ENIC_DEVARG_IG_VLAN_REWRITE "=trunk|untag|priority|pass");
765