xref: /dpdk/drivers/net/mvneta/mvneta_ethdev.c (revision 4ccc8d77)
1*4ccc8d77SZyta Szpak /* SPDX-License-Identifier: BSD-3-Clause
2*4ccc8d77SZyta Szpak  * Copyright(c) 2018 Marvell International Ltd.
3*4ccc8d77SZyta Szpak  * Copyright(c) 2018 Semihalf.
4*4ccc8d77SZyta Szpak  * All rights reserved.
5*4ccc8d77SZyta Szpak  */
6*4ccc8d77SZyta Szpak 
7*4ccc8d77SZyta Szpak #include <rte_ethdev_driver.h>
8*4ccc8d77SZyta Szpak #include <rte_kvargs.h>
9*4ccc8d77SZyta Szpak #include <rte_log.h>
10*4ccc8d77SZyta Szpak #include <rte_malloc.h>
11*4ccc8d77SZyta Szpak #include <rte_bus_vdev.h>
12*4ccc8d77SZyta Szpak 
13*4ccc8d77SZyta Szpak #include <stdio.h>
14*4ccc8d77SZyta Szpak #include <fcntl.h>
15*4ccc8d77SZyta Szpak #include <linux/ethtool.h>
16*4ccc8d77SZyta Szpak #include <linux/sockios.h>
17*4ccc8d77SZyta Szpak #include <net/if.h>
18*4ccc8d77SZyta Szpak #include <net/if_arp.h>
19*4ccc8d77SZyta Szpak #include <sys/ioctl.h>
20*4ccc8d77SZyta Szpak #include <sys/socket.h>
21*4ccc8d77SZyta Szpak #include <sys/stat.h>
22*4ccc8d77SZyta Szpak #include <sys/types.h>
23*4ccc8d77SZyta Szpak 
24*4ccc8d77SZyta Szpak #include <rte_mvep_common.h>
25*4ccc8d77SZyta Szpak 
26*4ccc8d77SZyta Szpak #include "mvneta_ethdev.h"
27*4ccc8d77SZyta Szpak 
28*4ccc8d77SZyta Szpak 
29*4ccc8d77SZyta Szpak #define MVNETA_IFACE_NAME_ARG "iface"
30*4ccc8d77SZyta Szpak 
31*4ccc8d77SZyta Szpak #define MVNETA_RX_OFFLOADS (DEV_RX_OFFLOAD_JUMBO_FRAME | \
32*4ccc8d77SZyta Szpak 			  DEV_RX_OFFLOAD_CHECKSUM)
33*4ccc8d77SZyta Szpak 
34*4ccc8d77SZyta Szpak /** Port Tx offloads capabilities */
35*4ccc8d77SZyta Szpak #define MVNETA_TX_OFFLOADS (DEV_TX_OFFLOAD_IPV4_CKSUM | \
36*4ccc8d77SZyta Szpak 			  DEV_TX_OFFLOAD_UDP_CKSUM | \
37*4ccc8d77SZyta Szpak 			  DEV_TX_OFFLOAD_TCP_CKSUM | \
38*4ccc8d77SZyta Szpak 			  DEV_TX_OFFLOAD_MULTI_SEGS)
39*4ccc8d77SZyta Szpak 
40*4ccc8d77SZyta Szpak #define MVNETA_PKT_SIZE_MAX (16382 - MV_MH_SIZE) /* 9700B */
41*4ccc8d77SZyta Szpak #define MVNETA_DEFAULT_MTU 1500
42*4ccc8d77SZyta Szpak 
43*4ccc8d77SZyta Szpak #define MVNETA_MAC_ADDRS_MAX 256 /*16 UC, 256 IP, 256 MC/BC */
44*4ccc8d77SZyta Szpak /** Maximum length of a match string */
45*4ccc8d77SZyta Szpak #define MVNETA_MATCH_LEN 16
46*4ccc8d77SZyta Szpak 
47*4ccc8d77SZyta Szpak int mvneta_logtype;
48*4ccc8d77SZyta Szpak 
49*4ccc8d77SZyta Szpak static const char * const valid_args[] = {
50*4ccc8d77SZyta Szpak 	MVNETA_IFACE_NAME_ARG,
51*4ccc8d77SZyta Szpak 	NULL
52*4ccc8d77SZyta Szpak };
53*4ccc8d77SZyta Szpak 
54*4ccc8d77SZyta Szpak struct mvneta_ifnames {
55*4ccc8d77SZyta Szpak 	const char *names[NETA_NUM_ETH_PPIO];
56*4ccc8d77SZyta Szpak 	int idx;
57*4ccc8d77SZyta Szpak };
58*4ccc8d77SZyta Szpak 
59*4ccc8d77SZyta Szpak static int mvneta_dev_num;
60*4ccc8d77SZyta Szpak 
61*4ccc8d77SZyta Szpak /**
62*4ccc8d77SZyta Szpak  * Deinitialize packet processor.
63*4ccc8d77SZyta Szpak  */
64*4ccc8d77SZyta Szpak static void
65*4ccc8d77SZyta Szpak mvneta_neta_deinit(void)
66*4ccc8d77SZyta Szpak {
67*4ccc8d77SZyta Szpak 	neta_deinit();
68*4ccc8d77SZyta Szpak }
69*4ccc8d77SZyta Szpak 
70*4ccc8d77SZyta Szpak /**
71*4ccc8d77SZyta Szpak  * Initialize packet processor.
72*4ccc8d77SZyta Szpak  *
73*4ccc8d77SZyta Szpak  * @return
74*4ccc8d77SZyta Szpak  *   0 on success, negative error value otherwise.
75*4ccc8d77SZyta Szpak  */
76*4ccc8d77SZyta Szpak static int
77*4ccc8d77SZyta Szpak mvneta_neta_init(void)
78*4ccc8d77SZyta Szpak {
79*4ccc8d77SZyta Szpak 	return neta_init();
80*4ccc8d77SZyta Szpak }
81*4ccc8d77SZyta Szpak 
82*4ccc8d77SZyta Szpak /**
83*4ccc8d77SZyta Szpak  * Callback used by rte_kvargs_process() during argument parsing.
84*4ccc8d77SZyta Szpak  *
85*4ccc8d77SZyta Szpak  * @param key
86*4ccc8d77SZyta Szpak  *   Pointer to the parsed key (unused).
87*4ccc8d77SZyta Szpak  * @param value
88*4ccc8d77SZyta Szpak  *   Pointer to the parsed value.
89*4ccc8d77SZyta Szpak  * @param extra_args
90*4ccc8d77SZyta Szpak  *   Pointer to the extra arguments which contains address of the
91*4ccc8d77SZyta Szpak  *   table of pointers to parsed interface names.
92*4ccc8d77SZyta Szpak  *
93*4ccc8d77SZyta Szpak  * @return
94*4ccc8d77SZyta Szpak  *   Always 0.
95*4ccc8d77SZyta Szpak  */
96*4ccc8d77SZyta Szpak static int
97*4ccc8d77SZyta Szpak mvneta_ifnames_get(const char *key __rte_unused, const char *value,
98*4ccc8d77SZyta Szpak 		 void *extra_args)
99*4ccc8d77SZyta Szpak {
100*4ccc8d77SZyta Szpak 	struct mvneta_ifnames *ifnames = extra_args;
101*4ccc8d77SZyta Szpak 
102*4ccc8d77SZyta Szpak 	ifnames->names[ifnames->idx++] = value;
103*4ccc8d77SZyta Szpak 
104*4ccc8d77SZyta Szpak 	return 0;
105*4ccc8d77SZyta Szpak }
106*4ccc8d77SZyta Szpak 
107*4ccc8d77SZyta Szpak /**
108*4ccc8d77SZyta Szpak  * Ethernet device configuration.
109*4ccc8d77SZyta Szpak  *
110*4ccc8d77SZyta Szpak  * Prepare the driver for a given number of TX and RX queues and
111*4ccc8d77SZyta Szpak  * configure RSS if supported.
112*4ccc8d77SZyta Szpak  *
113*4ccc8d77SZyta Szpak  * @param dev
114*4ccc8d77SZyta Szpak  *   Pointer to Ethernet device structure.
115*4ccc8d77SZyta Szpak  *
116*4ccc8d77SZyta Szpak  * @return
117*4ccc8d77SZyta Szpak  *   0 on success, negative error value otherwise.
118*4ccc8d77SZyta Szpak  */
119*4ccc8d77SZyta Szpak static int
120*4ccc8d77SZyta Szpak mvneta_dev_configure(struct rte_eth_dev *dev)
121*4ccc8d77SZyta Szpak {
122*4ccc8d77SZyta Szpak 	struct mvneta_priv *priv = dev->data->dev_private;
123*4ccc8d77SZyta Szpak 	struct neta_ppio_params *ppio_params;
124*4ccc8d77SZyta Szpak 
125*4ccc8d77SZyta Szpak 	if (dev->data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_NONE) {
126*4ccc8d77SZyta Szpak 		MVNETA_LOG(INFO, "Unsupported RSS and rx multi queue mode %d",
127*4ccc8d77SZyta Szpak 			dev->data->dev_conf.rxmode.mq_mode);
128*4ccc8d77SZyta Szpak 		if (dev->data->nb_rx_queues > 1)
129*4ccc8d77SZyta Szpak 			return -EINVAL;
130*4ccc8d77SZyta Szpak 	}
131*4ccc8d77SZyta Szpak 
132*4ccc8d77SZyta Szpak 	if (dev->data->dev_conf.rxmode.split_hdr_size) {
133*4ccc8d77SZyta Szpak 		MVNETA_LOG(INFO, "Split headers not supported");
134*4ccc8d77SZyta Szpak 		return -EINVAL;
135*4ccc8d77SZyta Szpak 	}
136*4ccc8d77SZyta Szpak 
137*4ccc8d77SZyta Szpak 	if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME)
138*4ccc8d77SZyta Szpak 		dev->data->mtu = dev->data->dev_conf.rxmode.max_rx_pkt_len -
139*4ccc8d77SZyta Szpak 				 MRVL_NETA_ETH_HDRS_LEN;
140*4ccc8d77SZyta Szpak 
141*4ccc8d77SZyta Szpak 	if (dev->data->dev_conf.txmode.offloads & DEV_TX_OFFLOAD_MULTI_SEGS)
142*4ccc8d77SZyta Szpak 		priv->multiseg = 1;
143*4ccc8d77SZyta Szpak 
144*4ccc8d77SZyta Szpak 	ppio_params = &priv->ppio_params;
145*4ccc8d77SZyta Szpak 	ppio_params->outqs_params.num_outqs = dev->data->nb_tx_queues;
146*4ccc8d77SZyta Szpak 	/* Default: 1 TC, no QoS supported. */
147*4ccc8d77SZyta Szpak 	ppio_params->inqs_params.num_tcs = 1;
148*4ccc8d77SZyta Szpak 	ppio_params->inqs_params.tcs_params[0].pkt_offset = MRVL_NETA_PKT_OFFS;
149*4ccc8d77SZyta Szpak 	priv->ppio_id = dev->data->port_id;
150*4ccc8d77SZyta Szpak 
151*4ccc8d77SZyta Szpak 	return 0;
152*4ccc8d77SZyta Szpak }
153*4ccc8d77SZyta Szpak 
154*4ccc8d77SZyta Szpak /**
155*4ccc8d77SZyta Szpak  * DPDK callback to get information about the device.
156*4ccc8d77SZyta Szpak  *
157*4ccc8d77SZyta Szpak  * @param dev
158*4ccc8d77SZyta Szpak  *   Pointer to Ethernet device structure (unused).
159*4ccc8d77SZyta Szpak  * @param info
160*4ccc8d77SZyta Szpak  *   Info structure output buffer.
161*4ccc8d77SZyta Szpak  */
162*4ccc8d77SZyta Szpak static void
163*4ccc8d77SZyta Szpak mvneta_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
164*4ccc8d77SZyta Szpak 		   struct rte_eth_dev_info *info)
165*4ccc8d77SZyta Szpak {
166*4ccc8d77SZyta Szpak 	info->speed_capa = ETH_LINK_SPEED_10M |
167*4ccc8d77SZyta Szpak 			   ETH_LINK_SPEED_100M |
168*4ccc8d77SZyta Szpak 			   ETH_LINK_SPEED_1G |
169*4ccc8d77SZyta Szpak 			   ETH_LINK_SPEED_2_5G;
170*4ccc8d77SZyta Szpak 
171*4ccc8d77SZyta Szpak 	info->max_rx_queues = MRVL_NETA_RXQ_MAX;
172*4ccc8d77SZyta Szpak 	info->max_tx_queues = MRVL_NETA_TXQ_MAX;
173*4ccc8d77SZyta Szpak 	info->max_mac_addrs = MVNETA_MAC_ADDRS_MAX;
174*4ccc8d77SZyta Szpak 
175*4ccc8d77SZyta Szpak 	info->rx_desc_lim.nb_max = MRVL_NETA_RXD_MAX;
176*4ccc8d77SZyta Szpak 	info->rx_desc_lim.nb_min = MRVL_NETA_RXD_MIN;
177*4ccc8d77SZyta Szpak 	info->rx_desc_lim.nb_align = MRVL_NETA_RXD_ALIGN;
178*4ccc8d77SZyta Szpak 
179*4ccc8d77SZyta Szpak 	info->tx_desc_lim.nb_max = MRVL_NETA_TXD_MAX;
180*4ccc8d77SZyta Szpak 	info->tx_desc_lim.nb_min = MRVL_NETA_TXD_MIN;
181*4ccc8d77SZyta Szpak 	info->tx_desc_lim.nb_align = MRVL_NETA_TXD_ALIGN;
182*4ccc8d77SZyta Szpak 
183*4ccc8d77SZyta Szpak 	info->rx_offload_capa = MVNETA_RX_OFFLOADS;
184*4ccc8d77SZyta Szpak 	info->rx_queue_offload_capa = MVNETA_RX_OFFLOADS;
185*4ccc8d77SZyta Szpak 
186*4ccc8d77SZyta Szpak 	info->tx_offload_capa =  MVNETA_TX_OFFLOADS;
187*4ccc8d77SZyta Szpak 	info->tx_queue_offload_capa =  MVNETA_TX_OFFLOADS;
188*4ccc8d77SZyta Szpak 
189*4ccc8d77SZyta Szpak 	/* By default packets are dropped if no descriptors are available */
190*4ccc8d77SZyta Szpak 	info->default_rxconf.rx_drop_en = 1;
191*4ccc8d77SZyta Szpak 	/* Deferred tx queue start is not supported */
192*4ccc8d77SZyta Szpak 	info->default_txconf.tx_deferred_start = 0;
193*4ccc8d77SZyta Szpak 	info->default_txconf.offloads = 0;
194*4ccc8d77SZyta Szpak 
195*4ccc8d77SZyta Szpak 	info->max_rx_pktlen = MVNETA_PKT_SIZE_MAX;
196*4ccc8d77SZyta Szpak }
197*4ccc8d77SZyta Szpak 
198*4ccc8d77SZyta Szpak /**
199*4ccc8d77SZyta Szpak  * Return supported packet types.
200*4ccc8d77SZyta Szpak  *
201*4ccc8d77SZyta Szpak  * @param dev
202*4ccc8d77SZyta Szpak  *   Pointer to Ethernet device structure (unused).
203*4ccc8d77SZyta Szpak  *
204*4ccc8d77SZyta Szpak  * @return
205*4ccc8d77SZyta Szpak  *   Const pointer to the table with supported packet types.
206*4ccc8d77SZyta Szpak  */
207*4ccc8d77SZyta Szpak static const uint32_t *
208*4ccc8d77SZyta Szpak mvneta_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
209*4ccc8d77SZyta Szpak {
210*4ccc8d77SZyta Szpak 	static const uint32_t ptypes[] = {
211*4ccc8d77SZyta Szpak 		RTE_PTYPE_L2_ETHER,
212*4ccc8d77SZyta Szpak 		RTE_PTYPE_L2_ETHER_VLAN,
213*4ccc8d77SZyta Szpak 		RTE_PTYPE_L3_IPV4,
214*4ccc8d77SZyta Szpak 		RTE_PTYPE_L3_IPV6,
215*4ccc8d77SZyta Szpak 		RTE_PTYPE_L4_TCP,
216*4ccc8d77SZyta Szpak 		RTE_PTYPE_L4_UDP
217*4ccc8d77SZyta Szpak 	};
218*4ccc8d77SZyta Szpak 
219*4ccc8d77SZyta Szpak 	return ptypes;
220*4ccc8d77SZyta Szpak }
221*4ccc8d77SZyta Szpak 
222*4ccc8d77SZyta Szpak /**
223*4ccc8d77SZyta Szpak  * DPDK callback to bring the link up.
224*4ccc8d77SZyta Szpak  *
225*4ccc8d77SZyta Szpak  * @param dev
226*4ccc8d77SZyta Szpak  *   Pointer to Ethernet device structure.
227*4ccc8d77SZyta Szpak  *
228*4ccc8d77SZyta Szpak  * @return
229*4ccc8d77SZyta Szpak  *   0 on success, negative error value otherwise.
230*4ccc8d77SZyta Szpak  */
231*4ccc8d77SZyta Szpak static int
232*4ccc8d77SZyta Szpak mvneta_dev_set_link_up(struct rte_eth_dev *dev)
233*4ccc8d77SZyta Szpak {
234*4ccc8d77SZyta Szpak 	struct mvneta_priv *priv = dev->data->dev_private;
235*4ccc8d77SZyta Szpak 
236*4ccc8d77SZyta Szpak 	if (!priv->ppio)
237*4ccc8d77SZyta Szpak 		return 0;
238*4ccc8d77SZyta Szpak 
239*4ccc8d77SZyta Szpak 	return neta_ppio_enable(priv->ppio);
240*4ccc8d77SZyta Szpak }
241*4ccc8d77SZyta Szpak 
242*4ccc8d77SZyta Szpak /**
243*4ccc8d77SZyta Szpak  * DPDK callback to bring the link down.
244*4ccc8d77SZyta Szpak  *
245*4ccc8d77SZyta Szpak  * @param dev
246*4ccc8d77SZyta Szpak  *   Pointer to Ethernet device structure.
247*4ccc8d77SZyta Szpak  *
248*4ccc8d77SZyta Szpak  * @return
249*4ccc8d77SZyta Szpak  *   0 on success, negative error value otherwise.
250*4ccc8d77SZyta Szpak  */
251*4ccc8d77SZyta Szpak static int
252*4ccc8d77SZyta Szpak mvneta_dev_set_link_down(struct rte_eth_dev *dev)
253*4ccc8d77SZyta Szpak {
254*4ccc8d77SZyta Szpak 	struct mvneta_priv *priv = dev->data->dev_private;
255*4ccc8d77SZyta Szpak 
256*4ccc8d77SZyta Szpak 	if (!priv->ppio)
257*4ccc8d77SZyta Szpak 		return 0;
258*4ccc8d77SZyta Szpak 
259*4ccc8d77SZyta Szpak 	return neta_ppio_disable(priv->ppio);
260*4ccc8d77SZyta Szpak }
261*4ccc8d77SZyta Szpak 
262*4ccc8d77SZyta Szpak /**
263*4ccc8d77SZyta Szpak  * DPDK callback to start the device.
264*4ccc8d77SZyta Szpak  *
265*4ccc8d77SZyta Szpak  * @param dev
266*4ccc8d77SZyta Szpak  *   Pointer to Ethernet device structure.
267*4ccc8d77SZyta Szpak  *
268*4ccc8d77SZyta Szpak  * @return
269*4ccc8d77SZyta Szpak  *   0 on success, negative errno value on failure.
270*4ccc8d77SZyta Szpak  */
271*4ccc8d77SZyta Szpak static int
272*4ccc8d77SZyta Szpak mvneta_dev_start(struct rte_eth_dev *dev)
273*4ccc8d77SZyta Szpak {
274*4ccc8d77SZyta Szpak 	struct mvneta_priv *priv = dev->data->dev_private;
275*4ccc8d77SZyta Szpak 	char match[MVNETA_MATCH_LEN];
276*4ccc8d77SZyta Szpak 	int ret = 0, i;
277*4ccc8d77SZyta Szpak 
278*4ccc8d77SZyta Szpak 	if (priv->ppio)
279*4ccc8d77SZyta Szpak 		return mvneta_dev_set_link_up(dev);
280*4ccc8d77SZyta Szpak 
281*4ccc8d77SZyta Szpak 	snprintf(match, sizeof(match), "%s", dev->data->name);
282*4ccc8d77SZyta Szpak 	priv->ppio_params.match = match;
283*4ccc8d77SZyta Szpak 	priv->ppio_params.inqs_params.mtu = dev->data->mtu;
284*4ccc8d77SZyta Szpak 
285*4ccc8d77SZyta Szpak 	ret = neta_ppio_init(&priv->ppio_params, &priv->ppio);
286*4ccc8d77SZyta Szpak 	if (ret) {
287*4ccc8d77SZyta Szpak 		MVNETA_LOG(ERR, "Failed to init ppio");
288*4ccc8d77SZyta Szpak 		return ret;
289*4ccc8d77SZyta Szpak 	}
290*4ccc8d77SZyta Szpak 	priv->ppio_id = priv->ppio->port_id;
291*4ccc8d77SZyta Szpak 
292*4ccc8d77SZyta Szpak 	/*
293*4ccc8d77SZyta Szpak 	 * In case there are some some stale uc/mc mac addresses flush them
294*4ccc8d77SZyta Szpak 	 * here. It cannot be done during mvneta_dev_close() as port information
295*4ccc8d77SZyta Szpak 	 * is already gone at that point (due to neta_ppio_deinit() in
296*4ccc8d77SZyta Szpak 	 * mvneta_dev_stop()).
297*4ccc8d77SZyta Szpak 	 */
298*4ccc8d77SZyta Szpak 	if (!priv->uc_mc_flushed) {
299*4ccc8d77SZyta Szpak 		ret = neta_ppio_flush_mac_addrs(priv->ppio, 0, 1);
300*4ccc8d77SZyta Szpak 		if (ret) {
301*4ccc8d77SZyta Szpak 			MVNETA_LOG(ERR,
302*4ccc8d77SZyta Szpak 				"Failed to flush uc/mc filter list");
303*4ccc8d77SZyta Szpak 			goto out;
304*4ccc8d77SZyta Szpak 		}
305*4ccc8d77SZyta Szpak 		priv->uc_mc_flushed = 1;
306*4ccc8d77SZyta Szpak 	}
307*4ccc8d77SZyta Szpak 
308*4ccc8d77SZyta Szpak 	ret = mvneta_dev_set_link_up(dev);
309*4ccc8d77SZyta Szpak 	if (ret) {
310*4ccc8d77SZyta Szpak 		MVNETA_LOG(ERR, "Failed to set link up");
311*4ccc8d77SZyta Szpak 		goto out;
312*4ccc8d77SZyta Szpak 	}
313*4ccc8d77SZyta Szpak 
314*4ccc8d77SZyta Szpak 	/* start tx queues */
315*4ccc8d77SZyta Szpak 	for (i = 0; i < dev->data->nb_tx_queues; i++)
316*4ccc8d77SZyta Szpak 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
317*4ccc8d77SZyta Szpak 
318*4ccc8d77SZyta Szpak 	return 0;
319*4ccc8d77SZyta Szpak 
320*4ccc8d77SZyta Szpak out:
321*4ccc8d77SZyta Szpak 	MVNETA_LOG(ERR, "Failed to start device");
322*4ccc8d77SZyta Szpak 	neta_ppio_deinit(priv->ppio);
323*4ccc8d77SZyta Szpak 	return ret;
324*4ccc8d77SZyta Szpak }
325*4ccc8d77SZyta Szpak 
326*4ccc8d77SZyta Szpak /**
327*4ccc8d77SZyta Szpak  * DPDK callback to stop the device.
328*4ccc8d77SZyta Szpak  *
329*4ccc8d77SZyta Szpak  * @param dev
330*4ccc8d77SZyta Szpak  *   Pointer to Ethernet device structure.
331*4ccc8d77SZyta Szpak  */
332*4ccc8d77SZyta Szpak static void
333*4ccc8d77SZyta Szpak mvneta_dev_stop(struct rte_eth_dev *dev)
334*4ccc8d77SZyta Szpak {
335*4ccc8d77SZyta Szpak 	struct mvneta_priv *priv = dev->data->dev_private;
336*4ccc8d77SZyta Szpak 
337*4ccc8d77SZyta Szpak 	if (!priv->ppio)
338*4ccc8d77SZyta Szpak 		return;
339*4ccc8d77SZyta Szpak 
340*4ccc8d77SZyta Szpak 	mvneta_dev_set_link_down(dev);
341*4ccc8d77SZyta Szpak 
342*4ccc8d77SZyta Szpak 	neta_ppio_deinit(priv->ppio);
343*4ccc8d77SZyta Szpak 
344*4ccc8d77SZyta Szpak 	priv->ppio = NULL;
345*4ccc8d77SZyta Szpak }
346*4ccc8d77SZyta Szpak 
347*4ccc8d77SZyta Szpak /**
348*4ccc8d77SZyta Szpak  * DPDK callback to close the device.
349*4ccc8d77SZyta Szpak  *
350*4ccc8d77SZyta Szpak  * @param dev
351*4ccc8d77SZyta Szpak  *   Pointer to Ethernet device structure.
352*4ccc8d77SZyta Szpak  */
353*4ccc8d77SZyta Szpak static void
354*4ccc8d77SZyta Szpak mvneta_dev_close(struct rte_eth_dev *dev)
355*4ccc8d77SZyta Szpak {
356*4ccc8d77SZyta Szpak 	struct mvneta_priv *priv = dev->data->dev_private;
357*4ccc8d77SZyta Szpak 
358*4ccc8d77SZyta Szpak 	if (priv->ppio)
359*4ccc8d77SZyta Szpak 		mvneta_dev_stop(dev);
360*4ccc8d77SZyta Szpak }
361*4ccc8d77SZyta Szpak 
362*4ccc8d77SZyta Szpak /**
363*4ccc8d77SZyta Szpak  * DPDK callback to set the primary MAC address.
364*4ccc8d77SZyta Szpak  *
365*4ccc8d77SZyta Szpak  * @param dev
366*4ccc8d77SZyta Szpak  *   Pointer to Ethernet device structure.
367*4ccc8d77SZyta Szpak  * @param mac_addr
368*4ccc8d77SZyta Szpak  *   MAC address to register.
369*4ccc8d77SZyta Szpak  */
370*4ccc8d77SZyta Szpak static int
371*4ccc8d77SZyta Szpak mvneta_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
372*4ccc8d77SZyta Szpak {
373*4ccc8d77SZyta Szpak 	struct mvneta_priv *priv = dev->data->dev_private;
374*4ccc8d77SZyta Szpak 	int ret;
375*4ccc8d77SZyta Szpak 
376*4ccc8d77SZyta Szpak 	if (!priv->ppio)
377*4ccc8d77SZyta Szpak 		return -EINVAL;
378*4ccc8d77SZyta Szpak 
379*4ccc8d77SZyta Szpak 	ret = neta_ppio_set_mac_addr(priv->ppio, mac_addr->addr_bytes);
380*4ccc8d77SZyta Szpak 	if (ret) {
381*4ccc8d77SZyta Szpak 		char buf[ETHER_ADDR_FMT_SIZE];
382*4ccc8d77SZyta Szpak 		ether_format_addr(buf, sizeof(buf), mac_addr);
383*4ccc8d77SZyta Szpak 		MVNETA_LOG(ERR, "Failed to set mac to %s", buf);
384*4ccc8d77SZyta Szpak 	}
385*4ccc8d77SZyta Szpak 	return 0;
386*4ccc8d77SZyta Szpak }
387*4ccc8d77SZyta Szpak 
388*4ccc8d77SZyta Szpak static const struct eth_dev_ops mvneta_ops = {
389*4ccc8d77SZyta Szpak 	.dev_configure = mvneta_dev_configure,
390*4ccc8d77SZyta Szpak 	.dev_start = mvneta_dev_start,
391*4ccc8d77SZyta Szpak 	.dev_stop = mvneta_dev_stop,
392*4ccc8d77SZyta Szpak 	.dev_set_link_up = mvneta_dev_set_link_up,
393*4ccc8d77SZyta Szpak 	.dev_set_link_down = mvneta_dev_set_link_down,
394*4ccc8d77SZyta Szpak 	.dev_close = mvneta_dev_close,
395*4ccc8d77SZyta Szpak 	.mac_addr_set = mvneta_mac_addr_set,
396*4ccc8d77SZyta Szpak 	.dev_infos_get = mvneta_dev_infos_get,
397*4ccc8d77SZyta Szpak 	.dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
398*4ccc8d77SZyta Szpak };
399*4ccc8d77SZyta Szpak 
400*4ccc8d77SZyta Szpak /**
401*4ccc8d77SZyta Szpak  * Create device representing Ethernet port.
402*4ccc8d77SZyta Szpak  *
403*4ccc8d77SZyta Szpak  * @param name
404*4ccc8d77SZyta Szpak  *   Pointer to the port's name.
405*4ccc8d77SZyta Szpak  *
406*4ccc8d77SZyta Szpak  * @return
407*4ccc8d77SZyta Szpak  *   0 on success, negative error value otherwise.
408*4ccc8d77SZyta Szpak  */
409*4ccc8d77SZyta Szpak static int
410*4ccc8d77SZyta Szpak mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
411*4ccc8d77SZyta Szpak {
412*4ccc8d77SZyta Szpak 	int ret, fd = socket(AF_INET, SOCK_DGRAM, 0);
413*4ccc8d77SZyta Szpak 	struct rte_eth_dev *eth_dev;
414*4ccc8d77SZyta Szpak 	struct mvneta_priv *priv;
415*4ccc8d77SZyta Szpak 	struct ifreq req;
416*4ccc8d77SZyta Szpak 
417*4ccc8d77SZyta Szpak 	eth_dev = rte_eth_dev_allocate(name);
418*4ccc8d77SZyta Szpak 	if (!eth_dev)
419*4ccc8d77SZyta Szpak 		return -ENOMEM;
420*4ccc8d77SZyta Szpak 
421*4ccc8d77SZyta Szpak 	priv = rte_zmalloc_socket(name, sizeof(*priv), 0, rte_socket_id());
422*4ccc8d77SZyta Szpak 	if (!priv) {
423*4ccc8d77SZyta Szpak 		ret = -ENOMEM;
424*4ccc8d77SZyta Szpak 		goto out_free_dev;
425*4ccc8d77SZyta Szpak 	}
426*4ccc8d77SZyta Szpak 
427*4ccc8d77SZyta Szpak 	eth_dev->data->mac_addrs =
428*4ccc8d77SZyta Szpak 		rte_zmalloc("mac_addrs",
429*4ccc8d77SZyta Szpak 			    ETHER_ADDR_LEN * MVNETA_MAC_ADDRS_MAX, 0);
430*4ccc8d77SZyta Szpak 	if (!eth_dev->data->mac_addrs) {
431*4ccc8d77SZyta Szpak 		MVNETA_LOG(ERR, "Failed to allocate space for eth addrs");
432*4ccc8d77SZyta Szpak 		ret = -ENOMEM;
433*4ccc8d77SZyta Szpak 		goto out_free_priv;
434*4ccc8d77SZyta Szpak 	}
435*4ccc8d77SZyta Szpak 
436*4ccc8d77SZyta Szpak 	memset(&req, 0, sizeof(req));
437*4ccc8d77SZyta Szpak 	strcpy(req.ifr_name, name);
438*4ccc8d77SZyta Szpak 	ret = ioctl(fd, SIOCGIFHWADDR, &req);
439*4ccc8d77SZyta Szpak 	if (ret)
440*4ccc8d77SZyta Szpak 		goto out_free_mac;
441*4ccc8d77SZyta Szpak 
442*4ccc8d77SZyta Szpak 	memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
443*4ccc8d77SZyta Szpak 	       req.ifr_addr.sa_data, ETHER_ADDR_LEN);
444*4ccc8d77SZyta Szpak 
445*4ccc8d77SZyta Szpak 	eth_dev->data->kdrv = RTE_KDRV_NONE;
446*4ccc8d77SZyta Szpak 	eth_dev->data->dev_private = priv;
447*4ccc8d77SZyta Szpak 	eth_dev->device = &vdev->device;
448*4ccc8d77SZyta Szpak 	eth_dev->dev_ops = &mvneta_ops;
449*4ccc8d77SZyta Szpak 
450*4ccc8d77SZyta Szpak 	rte_eth_dev_probing_finish(eth_dev);
451*4ccc8d77SZyta Szpak 	return 0;
452*4ccc8d77SZyta Szpak out_free_mac:
453*4ccc8d77SZyta Szpak 	rte_free(eth_dev->data->mac_addrs);
454*4ccc8d77SZyta Szpak out_free_priv:
455*4ccc8d77SZyta Szpak 	rte_free(priv);
456*4ccc8d77SZyta Szpak out_free_dev:
457*4ccc8d77SZyta Szpak 	rte_eth_dev_release_port(eth_dev);
458*4ccc8d77SZyta Szpak 
459*4ccc8d77SZyta Szpak 	return ret;
460*4ccc8d77SZyta Szpak }
461*4ccc8d77SZyta Szpak 
462*4ccc8d77SZyta Szpak /**
463*4ccc8d77SZyta Szpak  * Cleanup previously created device representing Ethernet port.
464*4ccc8d77SZyta Szpak  *
465*4ccc8d77SZyta Szpak  * @param eth_dev
466*4ccc8d77SZyta Szpak  *   Pointer to the corresponding rte_eth_dev structure.
467*4ccc8d77SZyta Szpak  */
468*4ccc8d77SZyta Szpak static void
469*4ccc8d77SZyta Szpak mvneta_eth_dev_destroy(struct rte_eth_dev *eth_dev)
470*4ccc8d77SZyta Szpak {
471*4ccc8d77SZyta Szpak 	rte_free(eth_dev->data->dev_private);
472*4ccc8d77SZyta Szpak 	rte_free(eth_dev->data->mac_addrs);
473*4ccc8d77SZyta Szpak 	rte_eth_dev_release_port(eth_dev);
474*4ccc8d77SZyta Szpak }
475*4ccc8d77SZyta Szpak 
476*4ccc8d77SZyta Szpak /**
477*4ccc8d77SZyta Szpak  * Cleanup previously created device representing Ethernet port.
478*4ccc8d77SZyta Szpak  *
479*4ccc8d77SZyta Szpak  * @param name
480*4ccc8d77SZyta Szpak  *   Pointer to the port name.
481*4ccc8d77SZyta Szpak  */
482*4ccc8d77SZyta Szpak static void
483*4ccc8d77SZyta Szpak mvneta_eth_dev_destroy_name(const char *name)
484*4ccc8d77SZyta Szpak {
485*4ccc8d77SZyta Szpak 	struct rte_eth_dev *eth_dev;
486*4ccc8d77SZyta Szpak 
487*4ccc8d77SZyta Szpak 	eth_dev = rte_eth_dev_allocated(name);
488*4ccc8d77SZyta Szpak 	if (!eth_dev)
489*4ccc8d77SZyta Szpak 		return;
490*4ccc8d77SZyta Szpak 
491*4ccc8d77SZyta Szpak 	mvneta_eth_dev_destroy(eth_dev);
492*4ccc8d77SZyta Szpak }
493*4ccc8d77SZyta Szpak 
494*4ccc8d77SZyta Szpak /**
495*4ccc8d77SZyta Szpak  * DPDK callback to register the virtual device.
496*4ccc8d77SZyta Szpak  *
497*4ccc8d77SZyta Szpak  * @param vdev
498*4ccc8d77SZyta Szpak  *   Pointer to the virtual device.
499*4ccc8d77SZyta Szpak  *
500*4ccc8d77SZyta Szpak  * @return
501*4ccc8d77SZyta Szpak  *   0 on success, negative error value otherwise.
502*4ccc8d77SZyta Szpak  */
503*4ccc8d77SZyta Szpak static int
504*4ccc8d77SZyta Szpak rte_pmd_mvneta_probe(struct rte_vdev_device *vdev)
505*4ccc8d77SZyta Szpak {
506*4ccc8d77SZyta Szpak 	struct rte_kvargs *kvlist;
507*4ccc8d77SZyta Szpak 	struct mvneta_ifnames ifnames;
508*4ccc8d77SZyta Szpak 	int ret = -EINVAL;
509*4ccc8d77SZyta Szpak 	uint32_t i, ifnum;
510*4ccc8d77SZyta Szpak 	const char *params;
511*4ccc8d77SZyta Szpak 
512*4ccc8d77SZyta Szpak 	params = rte_vdev_device_args(vdev);
513*4ccc8d77SZyta Szpak 	if (!params)
514*4ccc8d77SZyta Szpak 		return -EINVAL;
515*4ccc8d77SZyta Szpak 
516*4ccc8d77SZyta Szpak 	kvlist = rte_kvargs_parse(params, valid_args);
517*4ccc8d77SZyta Szpak 	if (!kvlist)
518*4ccc8d77SZyta Szpak 		return -EINVAL;
519*4ccc8d77SZyta Szpak 
520*4ccc8d77SZyta Szpak 	ifnum = rte_kvargs_count(kvlist, MVNETA_IFACE_NAME_ARG);
521*4ccc8d77SZyta Szpak 	if (ifnum > RTE_DIM(ifnames.names))
522*4ccc8d77SZyta Szpak 		goto out_free_kvlist;
523*4ccc8d77SZyta Szpak 
524*4ccc8d77SZyta Szpak 	ifnames.idx = 0;
525*4ccc8d77SZyta Szpak 	rte_kvargs_process(kvlist, MVNETA_IFACE_NAME_ARG,
526*4ccc8d77SZyta Szpak 			   mvneta_ifnames_get, &ifnames);
527*4ccc8d77SZyta Szpak 
528*4ccc8d77SZyta Szpak 	/*
529*4ccc8d77SZyta Szpak 	 * The below system initialization should be done only once,
530*4ccc8d77SZyta Szpak 	 * on the first provided configuration file
531*4ccc8d77SZyta Szpak 	 */
532*4ccc8d77SZyta Szpak 	if (mvneta_dev_num)
533*4ccc8d77SZyta Szpak 		goto init_devices;
534*4ccc8d77SZyta Szpak 
535*4ccc8d77SZyta Szpak 	MVNETA_LOG(INFO, "Perform MUSDK initializations");
536*4ccc8d77SZyta Szpak 
537*4ccc8d77SZyta Szpak 	ret = rte_mvep_init(MVEP_MOD_T_NETA, kvlist);
538*4ccc8d77SZyta Szpak 	if (ret)
539*4ccc8d77SZyta Szpak 		goto out_free_kvlist;
540*4ccc8d77SZyta Szpak 
541*4ccc8d77SZyta Szpak 	ret = mvneta_neta_init();
542*4ccc8d77SZyta Szpak 	if (ret) {
543*4ccc8d77SZyta Szpak 		MVNETA_LOG(ERR, "Failed to init NETA!");
544*4ccc8d77SZyta Szpak 		rte_mvep_deinit(MVEP_MOD_T_NETA);
545*4ccc8d77SZyta Szpak 		goto out_free_kvlist;
546*4ccc8d77SZyta Szpak 	}
547*4ccc8d77SZyta Szpak 
548*4ccc8d77SZyta Szpak init_devices:
549*4ccc8d77SZyta Szpak 	for (i = 0; i < ifnum; i++) {
550*4ccc8d77SZyta Szpak 		MVNETA_LOG(INFO, "Creating %s", ifnames.names[i]);
551*4ccc8d77SZyta Szpak 		ret = mvneta_eth_dev_create(vdev, ifnames.names[i]);
552*4ccc8d77SZyta Szpak 		if (ret)
553*4ccc8d77SZyta Szpak 			goto out_cleanup;
554*4ccc8d77SZyta Szpak 	}
555*4ccc8d77SZyta Szpak 	mvneta_dev_num += ifnum;
556*4ccc8d77SZyta Szpak 
557*4ccc8d77SZyta Szpak 	rte_kvargs_free(kvlist);
558*4ccc8d77SZyta Szpak 
559*4ccc8d77SZyta Szpak 	return 0;
560*4ccc8d77SZyta Szpak out_cleanup:
561*4ccc8d77SZyta Szpak 	for (; i > 0; i--)
562*4ccc8d77SZyta Szpak 		mvneta_eth_dev_destroy_name(ifnames.names[i]);
563*4ccc8d77SZyta Szpak 
564*4ccc8d77SZyta Szpak 	if (mvneta_dev_num == 0) {
565*4ccc8d77SZyta Szpak 		mvneta_neta_deinit();
566*4ccc8d77SZyta Szpak 		rte_mvep_deinit(MVEP_MOD_T_NETA);
567*4ccc8d77SZyta Szpak 	}
568*4ccc8d77SZyta Szpak out_free_kvlist:
569*4ccc8d77SZyta Szpak 	rte_kvargs_free(kvlist);
570*4ccc8d77SZyta Szpak 
571*4ccc8d77SZyta Szpak 	return ret;
572*4ccc8d77SZyta Szpak }
573*4ccc8d77SZyta Szpak 
574*4ccc8d77SZyta Szpak /**
575*4ccc8d77SZyta Szpak  * DPDK callback to remove virtual device.
576*4ccc8d77SZyta Szpak  *
577*4ccc8d77SZyta Szpak  * @param vdev
578*4ccc8d77SZyta Szpak  *   Pointer to the removed virtual device.
579*4ccc8d77SZyta Szpak  *
580*4ccc8d77SZyta Szpak  * @return
581*4ccc8d77SZyta Szpak  *   0 on success, negative error value otherwise.
582*4ccc8d77SZyta Szpak  */
583*4ccc8d77SZyta Szpak static int
584*4ccc8d77SZyta Szpak rte_pmd_mvneta_remove(struct rte_vdev_device *vdev)
585*4ccc8d77SZyta Szpak {
586*4ccc8d77SZyta Szpak 	int i;
587*4ccc8d77SZyta Szpak 	const char *name;
588*4ccc8d77SZyta Szpak 
589*4ccc8d77SZyta Szpak 	name = rte_vdev_device_name(vdev);
590*4ccc8d77SZyta Szpak 	if (!name)
591*4ccc8d77SZyta Szpak 		return -EINVAL;
592*4ccc8d77SZyta Szpak 
593*4ccc8d77SZyta Szpak 	MVNETA_LOG(INFO, "Removing %s", name);
594*4ccc8d77SZyta Szpak 
595*4ccc8d77SZyta Szpak 	RTE_ETH_FOREACH_DEV(i) {
596*4ccc8d77SZyta Szpak 		if (rte_eth_devices[i].device != &vdev->device)
597*4ccc8d77SZyta Szpak 			continue;
598*4ccc8d77SZyta Szpak 
599*4ccc8d77SZyta Szpak 		mvneta_eth_dev_destroy(&rte_eth_devices[i]);
600*4ccc8d77SZyta Szpak 		mvneta_dev_num--;
601*4ccc8d77SZyta Szpak 	}
602*4ccc8d77SZyta Szpak 
603*4ccc8d77SZyta Szpak 	if (mvneta_dev_num == 0) {
604*4ccc8d77SZyta Szpak 		MVNETA_LOG(INFO, "Perform MUSDK deinit");
605*4ccc8d77SZyta Szpak 		mvneta_neta_deinit();
606*4ccc8d77SZyta Szpak 		rte_mvep_deinit(MVEP_MOD_T_NETA);
607*4ccc8d77SZyta Szpak 	}
608*4ccc8d77SZyta Szpak 
609*4ccc8d77SZyta Szpak 	return 0;
610*4ccc8d77SZyta Szpak }
611*4ccc8d77SZyta Szpak 
612*4ccc8d77SZyta Szpak static struct rte_vdev_driver pmd_mvneta_drv = {
613*4ccc8d77SZyta Szpak 	.probe = rte_pmd_mvneta_probe,
614*4ccc8d77SZyta Szpak 	.remove = rte_pmd_mvneta_remove,
615*4ccc8d77SZyta Szpak };
616*4ccc8d77SZyta Szpak 
617*4ccc8d77SZyta Szpak RTE_PMD_REGISTER_VDEV(net_mvneta, pmd_mvneta_drv);
618*4ccc8d77SZyta Szpak RTE_PMD_REGISTER_PARAM_STRING(net_mvneta, "iface=<ifc>");
619*4ccc8d77SZyta Szpak 
620*4ccc8d77SZyta Szpak RTE_INIT(mvneta_init_log)
621*4ccc8d77SZyta Szpak {
622*4ccc8d77SZyta Szpak 	mvneta_logtype = rte_log_register("pmd.net.mvneta");
623*4ccc8d77SZyta Szpak 	if (mvneta_logtype >= 0)
624*4ccc8d77SZyta Szpak 		rte_log_set_level(mvneta_logtype, RTE_LOG_NOTICE);
625*4ccc8d77SZyta Szpak }
626