xref: /f-stack/dpdk/drivers/net/enic/enic_ethdev.c (revision 2bfe3f2e)
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>
40*2bfe3f2eSlogwang #include <rte_bus_pci.h>
41a9643ea8Slogwang #include <rte_ethdev.h>
42*2bfe3f2eSlogwang #include <rte_ethdev_pci.h>
43a9643ea8Slogwang #include <rte_string_fns.h>
44a9643ea8Slogwang 
45a9643ea8Slogwang #include "vnic_intr.h"
46a9643ea8Slogwang #include "vnic_cq.h"
47a9643ea8Slogwang #include "vnic_wq.h"
48a9643ea8Slogwang #include "vnic_rq.h"
49a9643ea8Slogwang #include "vnic_enet.h"
50a9643ea8Slogwang #include "enic.h"
51a9643ea8Slogwang 
52a9643ea8Slogwang #ifdef RTE_LIBRTE_ENIC_DEBUG
53a9643ea8Slogwang #define ENICPMD_FUNC_TRACE() \
54a9643ea8Slogwang 	RTE_LOG(DEBUG, PMD, "ENICPMD trace: %s\n", __func__)
55a9643ea8Slogwang #else
56a9643ea8Slogwang #define ENICPMD_FUNC_TRACE() (void)0
57a9643ea8Slogwang #endif
58a9643ea8Slogwang 
59a9643ea8Slogwang /*
60a9643ea8Slogwang  * The set of PCI devices this driver supports
61a9643ea8Slogwang  */
62a9643ea8Slogwang #define CISCO_PCI_VENDOR_ID 0x1137
63a9643ea8Slogwang static const struct rte_pci_id pci_id_enic_map[] = {
64a9643ea8Slogwang 	{ RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET) },
65a9643ea8Slogwang 	{ RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) },
66a9643ea8Slogwang 	{.vendor_id = 0, /* sentinel */},
67a9643ea8Slogwang };
68a9643ea8Slogwang 
69a9643ea8Slogwang static int
70a9643ea8Slogwang enicpmd_fdir_ctrl_func(struct rte_eth_dev *eth_dev,
71a9643ea8Slogwang 			enum rte_filter_op filter_op, void *arg)
72a9643ea8Slogwang {
73a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
74a9643ea8Slogwang 	int ret = 0;
75a9643ea8Slogwang 
76a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
77a9643ea8Slogwang 	if (filter_op == RTE_ETH_FILTER_NOP)
78a9643ea8Slogwang 		return 0;
79a9643ea8Slogwang 
80a9643ea8Slogwang 	if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH)
81a9643ea8Slogwang 		return -EINVAL;
82a9643ea8Slogwang 
83a9643ea8Slogwang 	switch (filter_op) {
84a9643ea8Slogwang 	case RTE_ETH_FILTER_ADD:
85a9643ea8Slogwang 	case RTE_ETH_FILTER_UPDATE:
86a9643ea8Slogwang 		ret = enic_fdir_add_fltr(enic,
87a9643ea8Slogwang 			(struct rte_eth_fdir_filter *)arg);
88a9643ea8Slogwang 		break;
89a9643ea8Slogwang 
90a9643ea8Slogwang 	case RTE_ETH_FILTER_DELETE:
91a9643ea8Slogwang 		ret = enic_fdir_del_fltr(enic,
92a9643ea8Slogwang 			(struct rte_eth_fdir_filter *)arg);
93a9643ea8Slogwang 		break;
94a9643ea8Slogwang 
95a9643ea8Slogwang 	case RTE_ETH_FILTER_STATS:
96a9643ea8Slogwang 		enic_fdir_stats_get(enic, (struct rte_eth_fdir_stats *)arg);
97a9643ea8Slogwang 		break;
98a9643ea8Slogwang 
99a9643ea8Slogwang 	case RTE_ETH_FILTER_FLUSH:
100a9643ea8Slogwang 		dev_warning(enic, "unsupported operation %u", filter_op);
101a9643ea8Slogwang 		ret = -ENOTSUP;
102a9643ea8Slogwang 		break;
103*2bfe3f2eSlogwang 	case RTE_ETH_FILTER_INFO:
104*2bfe3f2eSlogwang 		enic_fdir_info_get(enic, (struct rte_eth_fdir_info *)arg);
105*2bfe3f2eSlogwang 		break;
106a9643ea8Slogwang 	default:
107a9643ea8Slogwang 		dev_err(enic, "unknown operation %u", filter_op);
108a9643ea8Slogwang 		ret = -EINVAL;
109a9643ea8Slogwang 		break;
110a9643ea8Slogwang 	}
111a9643ea8Slogwang 	return ret;
112a9643ea8Slogwang }
113a9643ea8Slogwang 
114a9643ea8Slogwang static int
115a9643ea8Slogwang enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev,
116a9643ea8Slogwang 		     enum rte_filter_type filter_type,
117a9643ea8Slogwang 		     enum rte_filter_op filter_op,
118a9643ea8Slogwang 		     void *arg)
119a9643ea8Slogwang {
120*2bfe3f2eSlogwang 	int ret = 0;
121a9643ea8Slogwang 
122*2bfe3f2eSlogwang 	ENICPMD_FUNC_TRACE();
123*2bfe3f2eSlogwang 
124*2bfe3f2eSlogwang 	switch (filter_type) {
125*2bfe3f2eSlogwang 	case RTE_ETH_FILTER_GENERIC:
126*2bfe3f2eSlogwang 		if (filter_op != RTE_ETH_FILTER_GET)
127*2bfe3f2eSlogwang 			return -EINVAL;
128*2bfe3f2eSlogwang 		*(const void **)arg = &enic_flow_ops;
129*2bfe3f2eSlogwang 		break;
130*2bfe3f2eSlogwang 	case RTE_ETH_FILTER_FDIR:
131a9643ea8Slogwang 		ret = enicpmd_fdir_ctrl_func(dev, filter_op, arg);
132*2bfe3f2eSlogwang 		break;
133*2bfe3f2eSlogwang 	default:
134a9643ea8Slogwang 		dev_warning(enic, "Filter type (%d) not supported",
135a9643ea8Slogwang 			filter_type);
136*2bfe3f2eSlogwang 		ret = -EINVAL;
137*2bfe3f2eSlogwang 		break;
138*2bfe3f2eSlogwang 	}
139a9643ea8Slogwang 
140a9643ea8Slogwang 	return ret;
141a9643ea8Slogwang }
142a9643ea8Slogwang 
143a9643ea8Slogwang static void enicpmd_dev_tx_queue_release(void *txq)
144a9643ea8Slogwang {
145a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
146*2bfe3f2eSlogwang 
147*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
148*2bfe3f2eSlogwang 		return;
149*2bfe3f2eSlogwang 
150a9643ea8Slogwang 	enic_free_wq(txq);
151a9643ea8Slogwang }
152a9643ea8Slogwang 
153a9643ea8Slogwang static int enicpmd_dev_setup_intr(struct enic *enic)
154a9643ea8Slogwang {
155a9643ea8Slogwang 	int ret;
156a9643ea8Slogwang 	unsigned int index;
157a9643ea8Slogwang 
158a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
159a9643ea8Slogwang 
160a9643ea8Slogwang 	/* Are we done with the init of all the queues? */
161a9643ea8Slogwang 	for (index = 0; index < enic->cq_count; index++) {
162a9643ea8Slogwang 		if (!enic->cq[index].ctrl)
163a9643ea8Slogwang 			break;
164a9643ea8Slogwang 	}
165a9643ea8Slogwang 	if (enic->cq_count != index)
166a9643ea8Slogwang 		return 0;
167a9643ea8Slogwang 	for (index = 0; index < enic->wq_count; index++) {
168a9643ea8Slogwang 		if (!enic->wq[index].ctrl)
169a9643ea8Slogwang 			break;
170a9643ea8Slogwang 	}
171a9643ea8Slogwang 	if (enic->wq_count != index)
172a9643ea8Slogwang 		return 0;
173a9643ea8Slogwang 	/* check start of packet (SOP) RQs only in case scatter is disabled. */
174a9643ea8Slogwang 	for (index = 0; index < enic->rq_count; index++) {
175*2bfe3f2eSlogwang 		if (!enic->rq[enic_rte_rq_idx_to_sop_idx(index)].ctrl)
176a9643ea8Slogwang 			break;
177a9643ea8Slogwang 	}
178a9643ea8Slogwang 	if (enic->rq_count != index)
179a9643ea8Slogwang 		return 0;
180a9643ea8Slogwang 
181a9643ea8Slogwang 	ret = enic_alloc_intr_resources(enic);
182a9643ea8Slogwang 	if (ret) {
183a9643ea8Slogwang 		dev_err(enic, "alloc intr failed\n");
184a9643ea8Slogwang 		return ret;
185a9643ea8Slogwang 	}
186a9643ea8Slogwang 	enic_init_vnic_resources(enic);
187a9643ea8Slogwang 
188a9643ea8Slogwang 	ret = enic_setup_finish(enic);
189a9643ea8Slogwang 	if (ret)
190a9643ea8Slogwang 		dev_err(enic, "setup could not be finished\n");
191a9643ea8Slogwang 
192a9643ea8Slogwang 	return ret;
193a9643ea8Slogwang }
194a9643ea8Slogwang 
195a9643ea8Slogwang static int enicpmd_dev_tx_queue_setup(struct rte_eth_dev *eth_dev,
196a9643ea8Slogwang 	uint16_t queue_idx,
197a9643ea8Slogwang 	uint16_t nb_desc,
198a9643ea8Slogwang 	unsigned int socket_id,
199a9643ea8Slogwang 	__rte_unused const struct rte_eth_txconf *tx_conf)
200a9643ea8Slogwang {
201a9643ea8Slogwang 	int ret;
202a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
203a9643ea8Slogwang 
204*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
205*2bfe3f2eSlogwang 		return -E_RTE_SECONDARY;
206a9643ea8Slogwang 
207*2bfe3f2eSlogwang 	ENICPMD_FUNC_TRACE();
208*2bfe3f2eSlogwang 	RTE_ASSERT(queue_idx < enic->conf_wq_count);
209a9643ea8Slogwang 	eth_dev->data->tx_queues[queue_idx] = (void *)&enic->wq[queue_idx];
210a9643ea8Slogwang 
211a9643ea8Slogwang 	ret = enic_alloc_wq(enic, queue_idx, socket_id, nb_desc);
212a9643ea8Slogwang 	if (ret) {
213a9643ea8Slogwang 		dev_err(enic, "error in allocating wq\n");
214a9643ea8Slogwang 		return ret;
215a9643ea8Slogwang 	}
216a9643ea8Slogwang 
217a9643ea8Slogwang 	return enicpmd_dev_setup_intr(enic);
218a9643ea8Slogwang }
219a9643ea8Slogwang 
220a9643ea8Slogwang static int enicpmd_dev_tx_queue_start(struct rte_eth_dev *eth_dev,
221a9643ea8Slogwang 	uint16_t queue_idx)
222a9643ea8Slogwang {
223a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
224a9643ea8Slogwang 
225a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
226a9643ea8Slogwang 
227a9643ea8Slogwang 	enic_start_wq(enic, queue_idx);
228a9643ea8Slogwang 
229a9643ea8Slogwang 	return 0;
230a9643ea8Slogwang }
231a9643ea8Slogwang 
232a9643ea8Slogwang static int enicpmd_dev_tx_queue_stop(struct rte_eth_dev *eth_dev,
233a9643ea8Slogwang 	uint16_t queue_idx)
234a9643ea8Slogwang {
235a9643ea8Slogwang 	int ret;
236a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
237a9643ea8Slogwang 
238a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
239a9643ea8Slogwang 
240a9643ea8Slogwang 	ret = enic_stop_wq(enic, queue_idx);
241a9643ea8Slogwang 	if (ret)
242a9643ea8Slogwang 		dev_err(enic, "error in stopping wq %d\n", queue_idx);
243a9643ea8Slogwang 
244a9643ea8Slogwang 	return ret;
245a9643ea8Slogwang }
246a9643ea8Slogwang 
247a9643ea8Slogwang static int enicpmd_dev_rx_queue_start(struct rte_eth_dev *eth_dev,
248a9643ea8Slogwang 	uint16_t queue_idx)
249a9643ea8Slogwang {
250a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
251a9643ea8Slogwang 
252a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
253a9643ea8Slogwang 
254a9643ea8Slogwang 	enic_start_rq(enic, queue_idx);
255a9643ea8Slogwang 
256a9643ea8Slogwang 	return 0;
257a9643ea8Slogwang }
258a9643ea8Slogwang 
259a9643ea8Slogwang static int enicpmd_dev_rx_queue_stop(struct rte_eth_dev *eth_dev,
260a9643ea8Slogwang 	uint16_t queue_idx)
261a9643ea8Slogwang {
262a9643ea8Slogwang 	int ret;
263a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
264a9643ea8Slogwang 
265a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
266a9643ea8Slogwang 
267a9643ea8Slogwang 	ret = enic_stop_rq(enic, queue_idx);
268a9643ea8Slogwang 	if (ret)
269a9643ea8Slogwang 		dev_err(enic, "error in stopping rq %d\n", queue_idx);
270a9643ea8Slogwang 
271a9643ea8Slogwang 	return ret;
272a9643ea8Slogwang }
273a9643ea8Slogwang 
274a9643ea8Slogwang static void enicpmd_dev_rx_queue_release(void *rxq)
275a9643ea8Slogwang {
276a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
277*2bfe3f2eSlogwang 
278*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
279*2bfe3f2eSlogwang 		return;
280*2bfe3f2eSlogwang 
281a9643ea8Slogwang 	enic_free_rq(rxq);
282a9643ea8Slogwang }
283a9643ea8Slogwang 
284*2bfe3f2eSlogwang static uint32_t enicpmd_dev_rx_queue_count(struct rte_eth_dev *dev,
285*2bfe3f2eSlogwang 					   uint16_t rx_queue_id)
286*2bfe3f2eSlogwang {
287*2bfe3f2eSlogwang 	struct enic *enic = pmd_priv(dev);
288*2bfe3f2eSlogwang 	uint32_t queue_count = 0;
289*2bfe3f2eSlogwang 	struct vnic_cq *cq;
290*2bfe3f2eSlogwang 	uint32_t cq_tail;
291*2bfe3f2eSlogwang 	uint16_t cq_idx;
292*2bfe3f2eSlogwang 	int rq_num;
293*2bfe3f2eSlogwang 
294*2bfe3f2eSlogwang 	rq_num = enic_rte_rq_idx_to_sop_idx(rx_queue_id);
295*2bfe3f2eSlogwang 	cq = &enic->cq[enic_cq_rq(enic, rq_num)];
296*2bfe3f2eSlogwang 	cq_idx = cq->to_clean;
297*2bfe3f2eSlogwang 
298*2bfe3f2eSlogwang 	cq_tail = ioread32(&cq->ctrl->cq_tail);
299*2bfe3f2eSlogwang 
300*2bfe3f2eSlogwang 	if (cq_tail < cq_idx)
301*2bfe3f2eSlogwang 		cq_tail += cq->ring.desc_count;
302*2bfe3f2eSlogwang 
303*2bfe3f2eSlogwang 	queue_count = cq_tail - cq_idx;
304*2bfe3f2eSlogwang 
305*2bfe3f2eSlogwang 	return queue_count;
306*2bfe3f2eSlogwang }
307*2bfe3f2eSlogwang 
308a9643ea8Slogwang static int enicpmd_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
309a9643ea8Slogwang 	uint16_t queue_idx,
310a9643ea8Slogwang 	uint16_t nb_desc,
311a9643ea8Slogwang 	unsigned int socket_id,
312a9643ea8Slogwang 	const struct rte_eth_rxconf *rx_conf,
313a9643ea8Slogwang 	struct rte_mempool *mp)
314a9643ea8Slogwang {
315a9643ea8Slogwang 	int ret;
316a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
317a9643ea8Slogwang 
318a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
319a9643ea8Slogwang 
320*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
321*2bfe3f2eSlogwang 		return -E_RTE_SECONDARY;
322*2bfe3f2eSlogwang 	RTE_ASSERT(enic_rte_rq_idx_to_sop_idx(queue_idx) < enic->conf_rq_count);
323a9643ea8Slogwang 	eth_dev->data->rx_queues[queue_idx] =
324*2bfe3f2eSlogwang 		(void *)&enic->rq[enic_rte_rq_idx_to_sop_idx(queue_idx)];
325a9643ea8Slogwang 
326a9643ea8Slogwang 	ret = enic_alloc_rq(enic, queue_idx, socket_id, mp, nb_desc,
327a9643ea8Slogwang 			    rx_conf->rx_free_thresh);
328a9643ea8Slogwang 	if (ret) {
329a9643ea8Slogwang 		dev_err(enic, "error in allocating rq\n");
330a9643ea8Slogwang 		return ret;
331a9643ea8Slogwang 	}
332a9643ea8Slogwang 
333a9643ea8Slogwang 	return enicpmd_dev_setup_intr(enic);
334a9643ea8Slogwang }
335a9643ea8Slogwang 
336a9643ea8Slogwang static int enicpmd_vlan_filter_set(struct rte_eth_dev *eth_dev,
337a9643ea8Slogwang 	uint16_t vlan_id, int on)
338a9643ea8Slogwang {
339a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
340a9643ea8Slogwang 	int err;
341a9643ea8Slogwang 
342a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
343a9643ea8Slogwang 	if (on)
344a9643ea8Slogwang 		err = enic_add_vlan(enic, vlan_id);
345a9643ea8Slogwang 	else
346a9643ea8Slogwang 		err = enic_del_vlan(enic, vlan_id);
347a9643ea8Slogwang 	return err;
348a9643ea8Slogwang }
349a9643ea8Slogwang 
350*2bfe3f2eSlogwang static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
351a9643ea8Slogwang {
352a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
353a9643ea8Slogwang 
354a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
355a9643ea8Slogwang 
356a9643ea8Slogwang 	if (mask & ETH_VLAN_STRIP_MASK) {
357a9643ea8Slogwang 		if (eth_dev->data->dev_conf.rxmode.hw_vlan_strip)
358a9643ea8Slogwang 			enic->ig_vlan_strip_en = 1;
359a9643ea8Slogwang 		else
360a9643ea8Slogwang 			enic->ig_vlan_strip_en = 0;
361a9643ea8Slogwang 	}
362a9643ea8Slogwang 	enic_set_rss_nic_cfg(enic);
363a9643ea8Slogwang 
364a9643ea8Slogwang 
365a9643ea8Slogwang 	if (mask & ETH_VLAN_FILTER_MASK) {
366a9643ea8Slogwang 		dev_warning(enic,
367a9643ea8Slogwang 			"Configuration of VLAN filter is not supported\n");
368a9643ea8Slogwang 	}
369a9643ea8Slogwang 
370a9643ea8Slogwang 	if (mask & ETH_VLAN_EXTEND_MASK) {
371a9643ea8Slogwang 		dev_warning(enic,
372a9643ea8Slogwang 			"Configuration of extended VLAN is not supported\n");
373a9643ea8Slogwang 	}
374*2bfe3f2eSlogwang 
375*2bfe3f2eSlogwang 	return 0;
376a9643ea8Slogwang }
377a9643ea8Slogwang 
378a9643ea8Slogwang static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
379a9643ea8Slogwang {
380a9643ea8Slogwang 	int ret;
381a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
382a9643ea8Slogwang 
383*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
384*2bfe3f2eSlogwang 		return -E_RTE_SECONDARY;
385*2bfe3f2eSlogwang 
386a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
387a9643ea8Slogwang 	ret = enic_set_vnic_res(enic);
388a9643ea8Slogwang 	if (ret) {
389a9643ea8Slogwang 		dev_err(enic, "Set vNIC resource num  failed, aborting\n");
390a9643ea8Slogwang 		return ret;
391a9643ea8Slogwang 	}
392a9643ea8Slogwang 
393a9643ea8Slogwang 	if (eth_dev->data->dev_conf.rxmode.split_hdr_size &&
394a9643ea8Slogwang 		eth_dev->data->dev_conf.rxmode.header_split) {
395a9643ea8Slogwang 		/* Enable header-data-split */
396a9643ea8Slogwang 		enic_set_hdr_split_size(enic,
397a9643ea8Slogwang 			eth_dev->data->dev_conf.rxmode.split_hdr_size);
398a9643ea8Slogwang 	}
399a9643ea8Slogwang 
400a9643ea8Slogwang 	enic->hw_ip_checksum = eth_dev->data->dev_conf.rxmode.hw_ip_checksum;
401*2bfe3f2eSlogwang 	ret = enicpmd_vlan_offload_set(eth_dev, ETH_VLAN_STRIP_MASK);
402*2bfe3f2eSlogwang 
403*2bfe3f2eSlogwang 	return ret;
404a9643ea8Slogwang }
405a9643ea8Slogwang 
406a9643ea8Slogwang /* Start the device.
407a9643ea8Slogwang  * It returns 0 on success.
408a9643ea8Slogwang  */
409a9643ea8Slogwang static int enicpmd_dev_start(struct rte_eth_dev *eth_dev)
410a9643ea8Slogwang {
411a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
412a9643ea8Slogwang 
413*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
414*2bfe3f2eSlogwang 		return -E_RTE_SECONDARY;
415*2bfe3f2eSlogwang 
416a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
417a9643ea8Slogwang 	return enic_enable(enic);
418a9643ea8Slogwang }
419a9643ea8Slogwang 
420a9643ea8Slogwang /*
421a9643ea8Slogwang  * Stop device: disable rx and tx functions to allow for reconfiguring.
422a9643ea8Slogwang  */
423a9643ea8Slogwang static void enicpmd_dev_stop(struct rte_eth_dev *eth_dev)
424a9643ea8Slogwang {
425a9643ea8Slogwang 	struct rte_eth_link link;
426a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
427a9643ea8Slogwang 
428*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
429*2bfe3f2eSlogwang 		return;
430*2bfe3f2eSlogwang 
431a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
432a9643ea8Slogwang 	enic_disable(enic);
433a9643ea8Slogwang 	memset(&link, 0, sizeof(link));
434a9643ea8Slogwang 	rte_atomic64_cmpset((uint64_t *)&eth_dev->data->dev_link,
435a9643ea8Slogwang 		*(uint64_t *)&eth_dev->data->dev_link,
436a9643ea8Slogwang 		*(uint64_t *)&link);
437a9643ea8Slogwang }
438a9643ea8Slogwang 
439a9643ea8Slogwang /*
440a9643ea8Slogwang  * Stop device.
441a9643ea8Slogwang  */
442a9643ea8Slogwang static void enicpmd_dev_close(struct rte_eth_dev *eth_dev)
443a9643ea8Slogwang {
444a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
445a9643ea8Slogwang 
446a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
447a9643ea8Slogwang 	enic_remove(enic);
448a9643ea8Slogwang }
449a9643ea8Slogwang 
450a9643ea8Slogwang static int enicpmd_dev_link_update(struct rte_eth_dev *eth_dev,
451a9643ea8Slogwang 	__rte_unused int wait_to_complete)
452a9643ea8Slogwang {
453a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
454a9643ea8Slogwang 
455a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
456*2bfe3f2eSlogwang 	return enic_link_update(enic);
457a9643ea8Slogwang }
458a9643ea8Slogwang 
459*2bfe3f2eSlogwang static int enicpmd_dev_stats_get(struct rte_eth_dev *eth_dev,
460a9643ea8Slogwang 	struct rte_eth_stats *stats)
461a9643ea8Slogwang {
462a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
463a9643ea8Slogwang 
464a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
465*2bfe3f2eSlogwang 	return enic_dev_stats_get(enic, stats);
466a9643ea8Slogwang }
467a9643ea8Slogwang 
468a9643ea8Slogwang static void enicpmd_dev_stats_reset(struct rte_eth_dev *eth_dev)
469a9643ea8Slogwang {
470a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
471a9643ea8Slogwang 
472a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
473a9643ea8Slogwang 	enic_dev_stats_clear(enic);
474a9643ea8Slogwang }
475a9643ea8Slogwang 
476a9643ea8Slogwang static void enicpmd_dev_info_get(struct rte_eth_dev *eth_dev,
477a9643ea8Slogwang 	struct rte_eth_dev_info *device_info)
478a9643ea8Slogwang {
479a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
480a9643ea8Slogwang 
481a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
482*2bfe3f2eSlogwang 	device_info->pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
483a9643ea8Slogwang 	/* Scattered Rx uses two receive queues per rx queue exposed to dpdk */
484a9643ea8Slogwang 	device_info->max_rx_queues = enic->conf_rq_count / 2;
485a9643ea8Slogwang 	device_info->max_tx_queues = enic->conf_wq_count;
486a9643ea8Slogwang 	device_info->min_rx_bufsize = ENIC_MIN_MTU;
487a9643ea8Slogwang 	device_info->max_rx_pktlen = enic->max_mtu + ETHER_HDR_LEN + 4;
488*2bfe3f2eSlogwang 	device_info->max_mac_addrs = ENIC_MAX_MAC_ADDR;
489a9643ea8Slogwang 	device_info->rx_offload_capa =
490a9643ea8Slogwang 		DEV_RX_OFFLOAD_VLAN_STRIP |
491a9643ea8Slogwang 		DEV_RX_OFFLOAD_IPV4_CKSUM |
492a9643ea8Slogwang 		DEV_RX_OFFLOAD_UDP_CKSUM  |
493a9643ea8Slogwang 		DEV_RX_OFFLOAD_TCP_CKSUM;
494a9643ea8Slogwang 	device_info->tx_offload_capa =
495a9643ea8Slogwang 		DEV_TX_OFFLOAD_VLAN_INSERT |
496a9643ea8Slogwang 		DEV_TX_OFFLOAD_IPV4_CKSUM  |
497a9643ea8Slogwang 		DEV_TX_OFFLOAD_UDP_CKSUM   |
498*2bfe3f2eSlogwang 		DEV_TX_OFFLOAD_TCP_CKSUM   |
499*2bfe3f2eSlogwang 		DEV_TX_OFFLOAD_TCP_TSO;
500a9643ea8Slogwang 	device_info->default_rxconf = (struct rte_eth_rxconf) {
501a9643ea8Slogwang 		.rx_free_thresh = ENIC_DEFAULT_RX_FREE_THRESH
502a9643ea8Slogwang 	};
503a9643ea8Slogwang }
504a9643ea8Slogwang 
505a9643ea8Slogwang static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev)
506a9643ea8Slogwang {
507a9643ea8Slogwang 	static const uint32_t ptypes[] = {
508*2bfe3f2eSlogwang 		RTE_PTYPE_L2_ETHER,
509*2bfe3f2eSlogwang 		RTE_PTYPE_L2_ETHER_VLAN,
510a9643ea8Slogwang 		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
511a9643ea8Slogwang 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
512a9643ea8Slogwang 		RTE_PTYPE_L4_TCP,
513a9643ea8Slogwang 		RTE_PTYPE_L4_UDP,
514a9643ea8Slogwang 		RTE_PTYPE_L4_FRAG,
515a9643ea8Slogwang 		RTE_PTYPE_L4_NONFRAG,
516a9643ea8Slogwang 		RTE_PTYPE_UNKNOWN
517a9643ea8Slogwang 	};
518a9643ea8Slogwang 
519a9643ea8Slogwang 	if (dev->rx_pkt_burst == enic_recv_pkts)
520a9643ea8Slogwang 		return ptypes;
521a9643ea8Slogwang 	return NULL;
522a9643ea8Slogwang }
523a9643ea8Slogwang 
524a9643ea8Slogwang static void enicpmd_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
525a9643ea8Slogwang {
526a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
527a9643ea8Slogwang 
528*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
529*2bfe3f2eSlogwang 		return;
530*2bfe3f2eSlogwang 
531a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
532*2bfe3f2eSlogwang 
533a9643ea8Slogwang 	enic->promisc = 1;
534a9643ea8Slogwang 	enic_add_packet_filter(enic);
535a9643ea8Slogwang }
536a9643ea8Slogwang 
537a9643ea8Slogwang static void enicpmd_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
538a9643ea8Slogwang {
539a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
540a9643ea8Slogwang 
541*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
542*2bfe3f2eSlogwang 		return;
543*2bfe3f2eSlogwang 
544a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
545a9643ea8Slogwang 	enic->promisc = 0;
546a9643ea8Slogwang 	enic_add_packet_filter(enic);
547a9643ea8Slogwang }
548a9643ea8Slogwang 
549a9643ea8Slogwang static void enicpmd_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
550a9643ea8Slogwang {
551a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
552a9643ea8Slogwang 
553*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
554*2bfe3f2eSlogwang 		return;
555*2bfe3f2eSlogwang 
556a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
557a9643ea8Slogwang 	enic->allmulti = 1;
558a9643ea8Slogwang 	enic_add_packet_filter(enic);
559a9643ea8Slogwang }
560a9643ea8Slogwang 
561a9643ea8Slogwang static void enicpmd_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
562a9643ea8Slogwang {
563a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
564a9643ea8Slogwang 
565*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
566*2bfe3f2eSlogwang 		return;
567*2bfe3f2eSlogwang 
568a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
569a9643ea8Slogwang 	enic->allmulti = 0;
570a9643ea8Slogwang 	enic_add_packet_filter(enic);
571a9643ea8Slogwang }
572a9643ea8Slogwang 
573*2bfe3f2eSlogwang static int enicpmd_add_mac_addr(struct rte_eth_dev *eth_dev,
574a9643ea8Slogwang 	struct ether_addr *mac_addr,
575a9643ea8Slogwang 	__rte_unused uint32_t index, __rte_unused uint32_t pool)
576a9643ea8Slogwang {
577a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
578a9643ea8Slogwang 
579*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
580*2bfe3f2eSlogwang 		return -E_RTE_SECONDARY;
581*2bfe3f2eSlogwang 
582a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
583*2bfe3f2eSlogwang 	return enic_set_mac_address(enic, mac_addr->addr_bytes);
584a9643ea8Slogwang }
585a9643ea8Slogwang 
586*2bfe3f2eSlogwang static void enicpmd_remove_mac_addr(struct rte_eth_dev *eth_dev, uint32_t index)
587a9643ea8Slogwang {
588a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
589a9643ea8Slogwang 
590*2bfe3f2eSlogwang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
591*2bfe3f2eSlogwang 		return;
592*2bfe3f2eSlogwang 
593a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
594*2bfe3f2eSlogwang 	enic_del_mac_address(enic, index);
595a9643ea8Slogwang }
596a9643ea8Slogwang 
597a9643ea8Slogwang static int enicpmd_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
598a9643ea8Slogwang {
599a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
600a9643ea8Slogwang 
601a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
602a9643ea8Slogwang 	return enic_set_mtu(enic, mtu);
603a9643ea8Slogwang }
604a9643ea8Slogwang 
605a9643ea8Slogwang static const struct eth_dev_ops enicpmd_eth_dev_ops = {
606a9643ea8Slogwang 	.dev_configure        = enicpmd_dev_configure,
607a9643ea8Slogwang 	.dev_start            = enicpmd_dev_start,
608a9643ea8Slogwang 	.dev_stop             = enicpmd_dev_stop,
609a9643ea8Slogwang 	.dev_set_link_up      = NULL,
610a9643ea8Slogwang 	.dev_set_link_down    = NULL,
611a9643ea8Slogwang 	.dev_close            = enicpmd_dev_close,
612a9643ea8Slogwang 	.promiscuous_enable   = enicpmd_dev_promiscuous_enable,
613a9643ea8Slogwang 	.promiscuous_disable  = enicpmd_dev_promiscuous_disable,
614a9643ea8Slogwang 	.allmulticast_enable  = enicpmd_dev_allmulticast_enable,
615a9643ea8Slogwang 	.allmulticast_disable = enicpmd_dev_allmulticast_disable,
616a9643ea8Slogwang 	.link_update          = enicpmd_dev_link_update,
617a9643ea8Slogwang 	.stats_get            = enicpmd_dev_stats_get,
618a9643ea8Slogwang 	.stats_reset          = enicpmd_dev_stats_reset,
619a9643ea8Slogwang 	.queue_stats_mapping_set = NULL,
620a9643ea8Slogwang 	.dev_infos_get        = enicpmd_dev_info_get,
621a9643ea8Slogwang 	.dev_supported_ptypes_get = enicpmd_dev_supported_ptypes_get,
622a9643ea8Slogwang 	.mtu_set              = enicpmd_mtu_set,
623a9643ea8Slogwang 	.vlan_filter_set      = enicpmd_vlan_filter_set,
624a9643ea8Slogwang 	.vlan_tpid_set        = NULL,
625a9643ea8Slogwang 	.vlan_offload_set     = enicpmd_vlan_offload_set,
626a9643ea8Slogwang 	.vlan_strip_queue_set = NULL,
627a9643ea8Slogwang 	.rx_queue_start       = enicpmd_dev_rx_queue_start,
628a9643ea8Slogwang 	.rx_queue_stop        = enicpmd_dev_rx_queue_stop,
629a9643ea8Slogwang 	.tx_queue_start       = enicpmd_dev_tx_queue_start,
630a9643ea8Slogwang 	.tx_queue_stop        = enicpmd_dev_tx_queue_stop,
631a9643ea8Slogwang 	.rx_queue_setup       = enicpmd_dev_rx_queue_setup,
632a9643ea8Slogwang 	.rx_queue_release     = enicpmd_dev_rx_queue_release,
633*2bfe3f2eSlogwang 	.rx_queue_count       = enicpmd_dev_rx_queue_count,
634a9643ea8Slogwang 	.rx_descriptor_done   = NULL,
635a9643ea8Slogwang 	.tx_queue_setup       = enicpmd_dev_tx_queue_setup,
636a9643ea8Slogwang 	.tx_queue_release     = enicpmd_dev_tx_queue_release,
637a9643ea8Slogwang 	.dev_led_on           = NULL,
638a9643ea8Slogwang 	.dev_led_off          = NULL,
639a9643ea8Slogwang 	.flow_ctrl_get        = NULL,
640a9643ea8Slogwang 	.flow_ctrl_set        = NULL,
641a9643ea8Slogwang 	.priority_flow_ctrl_set = NULL,
642a9643ea8Slogwang 	.mac_addr_add         = enicpmd_add_mac_addr,
643a9643ea8Slogwang 	.mac_addr_remove      = enicpmd_remove_mac_addr,
644a9643ea8Slogwang 	.filter_ctrl          = enicpmd_dev_filter_ctrl,
645a9643ea8Slogwang };
646a9643ea8Slogwang 
647a9643ea8Slogwang struct enic *enicpmd_list_head = NULL;
648a9643ea8Slogwang /* Initialize the driver
649a9643ea8Slogwang  * It returns 0 on success.
650a9643ea8Slogwang  */
651a9643ea8Slogwang static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev)
652a9643ea8Slogwang {
653a9643ea8Slogwang 	struct rte_pci_device *pdev;
654a9643ea8Slogwang 	struct rte_pci_addr *addr;
655a9643ea8Slogwang 	struct enic *enic = pmd_priv(eth_dev);
656a9643ea8Slogwang 
657a9643ea8Slogwang 	ENICPMD_FUNC_TRACE();
658a9643ea8Slogwang 
659a9643ea8Slogwang 	enic->port_id = eth_dev->data->port_id;
660a9643ea8Slogwang 	enic->rte_dev = eth_dev;
661a9643ea8Slogwang 	eth_dev->dev_ops = &enicpmd_eth_dev_ops;
662a9643ea8Slogwang 	eth_dev->rx_pkt_burst = &enic_recv_pkts;
663a9643ea8Slogwang 	eth_dev->tx_pkt_burst = &enic_xmit_pkts;
664a9643ea8Slogwang 
665*2bfe3f2eSlogwang 	pdev = RTE_ETH_DEV_TO_PCI(eth_dev);
666a9643ea8Slogwang 	rte_eth_copy_pci_info(eth_dev, pdev);
667a9643ea8Slogwang 	enic->pdev = pdev;
668a9643ea8Slogwang 	addr = &pdev->addr;
669a9643ea8Slogwang 
670a9643ea8Slogwang 	snprintf(enic->bdf_name, ENICPMD_BDF_LENGTH, "%04x:%02x:%02x.%x",
671a9643ea8Slogwang 		addr->domain, addr->bus, addr->devid, addr->function);
672a9643ea8Slogwang 
673a9643ea8Slogwang 	return enic_probe(enic);
674a9643ea8Slogwang }
675a9643ea8Slogwang 
676*2bfe3f2eSlogwang static int eth_enic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
677*2bfe3f2eSlogwang 	struct rte_pci_device *pci_dev)
678a9643ea8Slogwang {
679*2bfe3f2eSlogwang 	return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct enic),
680*2bfe3f2eSlogwang 		eth_enicpmd_dev_init);
681a9643ea8Slogwang }
682a9643ea8Slogwang 
683*2bfe3f2eSlogwang static int eth_enic_pci_remove(struct rte_pci_device *pci_dev)
684*2bfe3f2eSlogwang {
685*2bfe3f2eSlogwang 	return rte_eth_dev_pci_generic_remove(pci_dev, NULL);
686*2bfe3f2eSlogwang }
687*2bfe3f2eSlogwang 
688*2bfe3f2eSlogwang static struct rte_pci_driver rte_enic_pmd = {
689*2bfe3f2eSlogwang 	.id_table = pci_id_enic_map,
690*2bfe3f2eSlogwang 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
691*2bfe3f2eSlogwang 	.probe = eth_enic_pci_probe,
692*2bfe3f2eSlogwang 	.remove = eth_enic_pci_remove,
693a9643ea8Slogwang };
694a9643ea8Slogwang 
695*2bfe3f2eSlogwang RTE_PMD_REGISTER_PCI(net_enic, rte_enic_pmd);
696*2bfe3f2eSlogwang RTE_PMD_REGISTER_PCI_TABLE(net_enic, pci_id_enic_map);
697*2bfe3f2eSlogwang RTE_PMD_REGISTER_KMOD_DEP(net_enic, "* igb_uio | uio_pci_generic | vfio-pci");
698