1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2d30ea906Sjfb8856606 * Copyright(c) 2018 Marvell International Ltd.
3d30ea906Sjfb8856606 * Copyright(c) 2018 Semihalf.
4d30ea906Sjfb8856606 * All rights reserved.
5d30ea906Sjfb8856606 */
6d30ea906Sjfb8856606
74418919fSjohnjiang #include <rte_string_fns.h>
8d30ea906Sjfb8856606 #include <rte_ethdev_driver.h>
9d30ea906Sjfb8856606 #include <rte_kvargs.h>
10d30ea906Sjfb8856606 #include <rte_bus_vdev.h>
11d30ea906Sjfb8856606
12d30ea906Sjfb8856606 #include <stdio.h>
13d30ea906Sjfb8856606 #include <fcntl.h>
14d30ea906Sjfb8856606 #include <linux/ethtool.h>
15d30ea906Sjfb8856606 #include <linux/sockios.h>
16d30ea906Sjfb8856606 #include <net/if.h>
17d30ea906Sjfb8856606 #include <net/if_arp.h>
18d30ea906Sjfb8856606 #include <sys/ioctl.h>
19d30ea906Sjfb8856606 #include <sys/socket.h>
20d30ea906Sjfb8856606 #include <sys/stat.h>
21d30ea906Sjfb8856606 #include <sys/types.h>
22d30ea906Sjfb8856606
23d30ea906Sjfb8856606 #include <rte_mvep_common.h>
24d30ea906Sjfb8856606
25d30ea906Sjfb8856606 #include "mvneta_rxtx.h"
26d30ea906Sjfb8856606
27d30ea906Sjfb8856606
28d30ea906Sjfb8856606 #define MVNETA_IFACE_NAME_ARG "iface"
29d30ea906Sjfb8856606
30d30ea906Sjfb8856606 #define MVNETA_PKT_SIZE_MAX (16382 - MV_MH_SIZE) /* 9700B */
31d30ea906Sjfb8856606 #define MVNETA_DEFAULT_MTU 1500
32d30ea906Sjfb8856606
33d30ea906Sjfb8856606 #define MVNETA_MAC_ADDRS_MAX 256 /*16 UC, 256 IP, 256 MC/BC */
34d30ea906Sjfb8856606 /** Maximum length of a match string */
35d30ea906Sjfb8856606 #define MVNETA_MATCH_LEN 16
36d30ea906Sjfb8856606
37d30ea906Sjfb8856606 static const char * const valid_args[] = {
38d30ea906Sjfb8856606 MVNETA_IFACE_NAME_ARG,
39d30ea906Sjfb8856606 NULL
40d30ea906Sjfb8856606 };
41d30ea906Sjfb8856606
42d30ea906Sjfb8856606 struct mvneta_ifnames {
43d30ea906Sjfb8856606 const char *names[NETA_NUM_ETH_PPIO];
44d30ea906Sjfb8856606 int idx;
45d30ea906Sjfb8856606 };
46d30ea906Sjfb8856606
47d30ea906Sjfb8856606 static int mvneta_dev_num;
48d30ea906Sjfb8856606
494418919fSjohnjiang static int mvneta_stats_reset(struct rte_eth_dev *dev);
504418919fSjohnjiang static int rte_pmd_mvneta_remove(struct rte_vdev_device *vdev);
514418919fSjohnjiang
524418919fSjohnjiang
53d30ea906Sjfb8856606 /**
54d30ea906Sjfb8856606 * Deinitialize packet processor.
55d30ea906Sjfb8856606 */
56d30ea906Sjfb8856606 static void
mvneta_neta_deinit(void)57d30ea906Sjfb8856606 mvneta_neta_deinit(void)
58d30ea906Sjfb8856606 {
59d30ea906Sjfb8856606 neta_deinit();
60d30ea906Sjfb8856606 }
61d30ea906Sjfb8856606
62d30ea906Sjfb8856606 /**
63d30ea906Sjfb8856606 * Initialize packet processor.
64d30ea906Sjfb8856606 *
65d30ea906Sjfb8856606 * @return
66d30ea906Sjfb8856606 * 0 on success, negative error value otherwise.
67d30ea906Sjfb8856606 */
68d30ea906Sjfb8856606 static int
mvneta_neta_init(void)69d30ea906Sjfb8856606 mvneta_neta_init(void)
70d30ea906Sjfb8856606 {
71d30ea906Sjfb8856606 return neta_init();
72d30ea906Sjfb8856606 }
73d30ea906Sjfb8856606
74d30ea906Sjfb8856606 /**
75d30ea906Sjfb8856606 * Callback used by rte_kvargs_process() during argument parsing.
76d30ea906Sjfb8856606 *
77d30ea906Sjfb8856606 * @param key
78d30ea906Sjfb8856606 * Pointer to the parsed key (unused).
79d30ea906Sjfb8856606 * @param value
80d30ea906Sjfb8856606 * Pointer to the parsed value.
81d30ea906Sjfb8856606 * @param extra_args
82d30ea906Sjfb8856606 * Pointer to the extra arguments which contains address of the
83d30ea906Sjfb8856606 * table of pointers to parsed interface names.
84d30ea906Sjfb8856606 *
85d30ea906Sjfb8856606 * @return
86d30ea906Sjfb8856606 * Always 0.
87d30ea906Sjfb8856606 */
88d30ea906Sjfb8856606 static int
mvneta_ifnames_get(const char * key __rte_unused,const char * value,void * extra_args)89d30ea906Sjfb8856606 mvneta_ifnames_get(const char *key __rte_unused, const char *value,
90d30ea906Sjfb8856606 void *extra_args)
91d30ea906Sjfb8856606 {
92d30ea906Sjfb8856606 struct mvneta_ifnames *ifnames = extra_args;
93d30ea906Sjfb8856606
94d30ea906Sjfb8856606 ifnames->names[ifnames->idx++] = value;
95d30ea906Sjfb8856606
96d30ea906Sjfb8856606 return 0;
97d30ea906Sjfb8856606 }
98d30ea906Sjfb8856606
99d30ea906Sjfb8856606 /**
100d30ea906Sjfb8856606 * Ethernet device configuration.
101d30ea906Sjfb8856606 *
102d30ea906Sjfb8856606 * Prepare the driver for a given number of TX and RX queues and
103d30ea906Sjfb8856606 * configure RSS if supported.
104d30ea906Sjfb8856606 *
105d30ea906Sjfb8856606 * @param dev
106d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
107d30ea906Sjfb8856606 *
108d30ea906Sjfb8856606 * @return
109d30ea906Sjfb8856606 * 0 on success, negative error value otherwise.
110d30ea906Sjfb8856606 */
111d30ea906Sjfb8856606 static int
mvneta_dev_configure(struct rte_eth_dev * dev)112d30ea906Sjfb8856606 mvneta_dev_configure(struct rte_eth_dev *dev)
113d30ea906Sjfb8856606 {
114d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
115d30ea906Sjfb8856606 struct neta_ppio_params *ppio_params;
116d30ea906Sjfb8856606
117d30ea906Sjfb8856606 if (dev->data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_NONE) {
118d30ea906Sjfb8856606 MVNETA_LOG(INFO, "Unsupported RSS and rx multi queue mode %d",
119d30ea906Sjfb8856606 dev->data->dev_conf.rxmode.mq_mode);
120d30ea906Sjfb8856606 if (dev->data->nb_rx_queues > 1)
121d30ea906Sjfb8856606 return -EINVAL;
122d30ea906Sjfb8856606 }
123d30ea906Sjfb8856606
124d30ea906Sjfb8856606 if (dev->data->dev_conf.rxmode.split_hdr_size) {
125d30ea906Sjfb8856606 MVNETA_LOG(INFO, "Split headers not supported");
126d30ea906Sjfb8856606 return -EINVAL;
127d30ea906Sjfb8856606 }
128d30ea906Sjfb8856606
129d30ea906Sjfb8856606 if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME)
130d30ea906Sjfb8856606 dev->data->mtu = dev->data->dev_conf.rxmode.max_rx_pkt_len -
131d30ea906Sjfb8856606 MRVL_NETA_ETH_HDRS_LEN;
132d30ea906Sjfb8856606
133d30ea906Sjfb8856606 if (dev->data->dev_conf.txmode.offloads & DEV_TX_OFFLOAD_MULTI_SEGS)
134d30ea906Sjfb8856606 priv->multiseg = 1;
135d30ea906Sjfb8856606
136d30ea906Sjfb8856606 ppio_params = &priv->ppio_params;
137d30ea906Sjfb8856606 ppio_params->outqs_params.num_outqs = dev->data->nb_tx_queues;
138d30ea906Sjfb8856606 /* Default: 1 TC, no QoS supported. */
139d30ea906Sjfb8856606 ppio_params->inqs_params.num_tcs = 1;
140d30ea906Sjfb8856606 ppio_params->inqs_params.tcs_params[0].pkt_offset = MRVL_NETA_PKT_OFFS;
141d30ea906Sjfb8856606 priv->ppio_id = dev->data->port_id;
142d30ea906Sjfb8856606
143d30ea906Sjfb8856606 return 0;
144d30ea906Sjfb8856606 }
145d30ea906Sjfb8856606
146d30ea906Sjfb8856606 /**
147d30ea906Sjfb8856606 * DPDK callback to get information about the device.
148d30ea906Sjfb8856606 *
149d30ea906Sjfb8856606 * @param dev
150d30ea906Sjfb8856606 * Pointer to Ethernet device structure (unused).
151d30ea906Sjfb8856606 * @param info
152d30ea906Sjfb8856606 * Info structure output buffer.
153d30ea906Sjfb8856606 */
1544418919fSjohnjiang static int
mvneta_dev_infos_get(struct rte_eth_dev * dev __rte_unused,struct rte_eth_dev_info * info)155d30ea906Sjfb8856606 mvneta_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
156d30ea906Sjfb8856606 struct rte_eth_dev_info *info)
157d30ea906Sjfb8856606 {
158d30ea906Sjfb8856606 info->speed_capa = ETH_LINK_SPEED_10M |
159d30ea906Sjfb8856606 ETH_LINK_SPEED_100M |
160d30ea906Sjfb8856606 ETH_LINK_SPEED_1G |
161d30ea906Sjfb8856606 ETH_LINK_SPEED_2_5G;
162d30ea906Sjfb8856606
163d30ea906Sjfb8856606 info->max_rx_queues = MRVL_NETA_RXQ_MAX;
164d30ea906Sjfb8856606 info->max_tx_queues = MRVL_NETA_TXQ_MAX;
165d30ea906Sjfb8856606 info->max_mac_addrs = MVNETA_MAC_ADDRS_MAX;
166d30ea906Sjfb8856606
167d30ea906Sjfb8856606 info->rx_desc_lim.nb_max = MRVL_NETA_RXD_MAX;
168d30ea906Sjfb8856606 info->rx_desc_lim.nb_min = MRVL_NETA_RXD_MIN;
169d30ea906Sjfb8856606 info->rx_desc_lim.nb_align = MRVL_NETA_RXD_ALIGN;
170d30ea906Sjfb8856606
171d30ea906Sjfb8856606 info->tx_desc_lim.nb_max = MRVL_NETA_TXD_MAX;
172d30ea906Sjfb8856606 info->tx_desc_lim.nb_min = MRVL_NETA_TXD_MIN;
173d30ea906Sjfb8856606 info->tx_desc_lim.nb_align = MRVL_NETA_TXD_ALIGN;
174d30ea906Sjfb8856606
175d30ea906Sjfb8856606 info->rx_offload_capa = MVNETA_RX_OFFLOADS;
176d30ea906Sjfb8856606 info->rx_queue_offload_capa = MVNETA_RX_OFFLOADS;
177d30ea906Sjfb8856606
178d30ea906Sjfb8856606 info->tx_offload_capa = MVNETA_TX_OFFLOADS;
179d30ea906Sjfb8856606 info->tx_queue_offload_capa = MVNETA_TX_OFFLOADS;
180d30ea906Sjfb8856606
181d30ea906Sjfb8856606 /* By default packets are dropped if no descriptors are available */
182d30ea906Sjfb8856606 info->default_rxconf.rx_drop_en = 1;
183d30ea906Sjfb8856606 /* Deferred tx queue start is not supported */
184d30ea906Sjfb8856606 info->default_txconf.tx_deferred_start = 0;
185d30ea906Sjfb8856606 info->default_txconf.offloads = 0;
186d30ea906Sjfb8856606
187d30ea906Sjfb8856606 info->max_rx_pktlen = MVNETA_PKT_SIZE_MAX;
1884418919fSjohnjiang
1894418919fSjohnjiang return 0;
190d30ea906Sjfb8856606 }
191d30ea906Sjfb8856606
192d30ea906Sjfb8856606 /**
193d30ea906Sjfb8856606 * Return supported packet types.
194d30ea906Sjfb8856606 *
195d30ea906Sjfb8856606 * @param dev
196d30ea906Sjfb8856606 * Pointer to Ethernet device structure (unused).
197d30ea906Sjfb8856606 *
198d30ea906Sjfb8856606 * @return
199d30ea906Sjfb8856606 * Const pointer to the table with supported packet types.
200d30ea906Sjfb8856606 */
201d30ea906Sjfb8856606 static const uint32_t *
mvneta_dev_supported_ptypes_get(struct rte_eth_dev * dev __rte_unused)202d30ea906Sjfb8856606 mvneta_dev_supported_ptypes_get(struct rte_eth_dev *dev __rte_unused)
203d30ea906Sjfb8856606 {
204d30ea906Sjfb8856606 static const uint32_t ptypes[] = {
205d30ea906Sjfb8856606 RTE_PTYPE_L2_ETHER,
206d30ea906Sjfb8856606 RTE_PTYPE_L2_ETHER_VLAN,
207d30ea906Sjfb8856606 RTE_PTYPE_L3_IPV4,
208d30ea906Sjfb8856606 RTE_PTYPE_L3_IPV6,
209d30ea906Sjfb8856606 RTE_PTYPE_L4_TCP,
210d30ea906Sjfb8856606 RTE_PTYPE_L4_UDP
211d30ea906Sjfb8856606 };
212d30ea906Sjfb8856606
213d30ea906Sjfb8856606 return ptypes;
214d30ea906Sjfb8856606 }
215d30ea906Sjfb8856606
216d30ea906Sjfb8856606 /**
217d30ea906Sjfb8856606 * DPDK callback to change the MTU.
218d30ea906Sjfb8856606 *
219d30ea906Sjfb8856606 * Setting the MTU affects hardware MRU (packets larger than the MRU
220d30ea906Sjfb8856606 * will be dropped).
221d30ea906Sjfb8856606 *
222d30ea906Sjfb8856606 * @param dev
223d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
224d30ea906Sjfb8856606 * @param mtu
225d30ea906Sjfb8856606 * New MTU.
226d30ea906Sjfb8856606 *
227d30ea906Sjfb8856606 * @return
228d30ea906Sjfb8856606 * 0 on success, negative error value otherwise.
229d30ea906Sjfb8856606 */
230d30ea906Sjfb8856606 static int
mvneta_mtu_set(struct rte_eth_dev * dev,uint16_t mtu)231d30ea906Sjfb8856606 mvneta_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
232d30ea906Sjfb8856606 {
233d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
234d30ea906Sjfb8856606 uint16_t mbuf_data_size = 0; /* SW buffer size */
235d30ea906Sjfb8856606 uint16_t mru;
236d30ea906Sjfb8856606 int ret;
237d30ea906Sjfb8856606
238d30ea906Sjfb8856606 mru = MRVL_NETA_MTU_TO_MRU(mtu);
239d30ea906Sjfb8856606 /*
240d30ea906Sjfb8856606 * min_rx_buf_size is equal to mbuf data size
241d30ea906Sjfb8856606 * if pmd didn't set it differently
242d30ea906Sjfb8856606 */
243d30ea906Sjfb8856606 mbuf_data_size = dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM;
244d30ea906Sjfb8856606 /* Prevent PMD from:
245d30ea906Sjfb8856606 * - setting mru greater than the mbuf size resulting in
246d30ea906Sjfb8856606 * hw and sw buffer size mismatch
247d30ea906Sjfb8856606 * - setting mtu that requires the support of scattered packets
248d30ea906Sjfb8856606 * when this feature has not been enabled/supported so far.
249d30ea906Sjfb8856606 */
250d30ea906Sjfb8856606 if (!dev->data->scattered_rx &&
251d30ea906Sjfb8856606 (mru + MRVL_NETA_PKT_OFFS > mbuf_data_size)) {
252d30ea906Sjfb8856606 mru = mbuf_data_size - MRVL_NETA_PKT_OFFS;
253d30ea906Sjfb8856606 mtu = MRVL_NETA_MRU_TO_MTU(mru);
254d30ea906Sjfb8856606 MVNETA_LOG(WARNING, "MTU too big, max MTU possible limitted by"
255d30ea906Sjfb8856606 " current mbuf size: %u. Set MTU to %u, MRU to %u",
256d30ea906Sjfb8856606 mbuf_data_size, mtu, mru);
257d30ea906Sjfb8856606 }
258d30ea906Sjfb8856606
2594418919fSjohnjiang if (mtu < RTE_ETHER_MIN_MTU || mru > MVNETA_PKT_SIZE_MAX) {
260d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Invalid MTU [%u] or MRU [%u]", mtu, mru);
261d30ea906Sjfb8856606 return -EINVAL;
262d30ea906Sjfb8856606 }
263d30ea906Sjfb8856606
264d30ea906Sjfb8856606 dev->data->mtu = mtu;
265d30ea906Sjfb8856606 dev->data->dev_conf.rxmode.max_rx_pkt_len = mru - MV_MH_SIZE;
266d30ea906Sjfb8856606
267d30ea906Sjfb8856606 if (!priv->ppio)
268d30ea906Sjfb8856606 /* It is OK. New MTU will be set later on mvneta_dev_start */
269d30ea906Sjfb8856606 return 0;
270d30ea906Sjfb8856606
271d30ea906Sjfb8856606 ret = neta_ppio_set_mru(priv->ppio, mru);
272d30ea906Sjfb8856606 if (ret) {
273d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to change MRU");
274d30ea906Sjfb8856606 return ret;
275d30ea906Sjfb8856606 }
276d30ea906Sjfb8856606
277d30ea906Sjfb8856606 ret = neta_ppio_set_mtu(priv->ppio, mtu);
278d30ea906Sjfb8856606 if (ret) {
279d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to change MTU");
280d30ea906Sjfb8856606 return ret;
281d30ea906Sjfb8856606 }
282d30ea906Sjfb8856606 MVNETA_LOG(INFO, "MTU changed to %u, MRU = %u", mtu, mru);
283d30ea906Sjfb8856606
284d30ea906Sjfb8856606 return 0;
285d30ea906Sjfb8856606 }
286d30ea906Sjfb8856606
287d30ea906Sjfb8856606 /**
288d30ea906Sjfb8856606 * DPDK callback to bring the link up.
289d30ea906Sjfb8856606 *
290d30ea906Sjfb8856606 * @param dev
291d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
292d30ea906Sjfb8856606 *
293d30ea906Sjfb8856606 * @return
294d30ea906Sjfb8856606 * 0 on success, negative error value otherwise.
295d30ea906Sjfb8856606 */
296d30ea906Sjfb8856606 static int
mvneta_dev_set_link_up(struct rte_eth_dev * dev)297d30ea906Sjfb8856606 mvneta_dev_set_link_up(struct rte_eth_dev *dev)
298d30ea906Sjfb8856606 {
299d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
300d30ea906Sjfb8856606
301d30ea906Sjfb8856606 if (!priv->ppio)
302d30ea906Sjfb8856606 return 0;
303d30ea906Sjfb8856606
304d30ea906Sjfb8856606 return neta_ppio_enable(priv->ppio);
305d30ea906Sjfb8856606 }
306d30ea906Sjfb8856606
307d30ea906Sjfb8856606 /**
308d30ea906Sjfb8856606 * DPDK callback to bring the link down.
309d30ea906Sjfb8856606 *
310d30ea906Sjfb8856606 * @param dev
311d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
312d30ea906Sjfb8856606 *
313d30ea906Sjfb8856606 * @return
314d30ea906Sjfb8856606 * 0 on success, negative error value otherwise.
315d30ea906Sjfb8856606 */
316d30ea906Sjfb8856606 static int
mvneta_dev_set_link_down(struct rte_eth_dev * dev)317d30ea906Sjfb8856606 mvneta_dev_set_link_down(struct rte_eth_dev *dev)
318d30ea906Sjfb8856606 {
319d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
320d30ea906Sjfb8856606
321d30ea906Sjfb8856606 if (!priv->ppio)
322d30ea906Sjfb8856606 return 0;
323d30ea906Sjfb8856606
324d30ea906Sjfb8856606 return neta_ppio_disable(priv->ppio);
325d30ea906Sjfb8856606 }
326d30ea906Sjfb8856606
327d30ea906Sjfb8856606 /**
328d30ea906Sjfb8856606 * DPDK callback to start the device.
329d30ea906Sjfb8856606 *
330d30ea906Sjfb8856606 * @param dev
331d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
332d30ea906Sjfb8856606 *
333d30ea906Sjfb8856606 * @return
334d30ea906Sjfb8856606 * 0 on success, negative errno value on failure.
335d30ea906Sjfb8856606 */
336d30ea906Sjfb8856606 static int
mvneta_dev_start(struct rte_eth_dev * dev)337d30ea906Sjfb8856606 mvneta_dev_start(struct rte_eth_dev *dev)
338d30ea906Sjfb8856606 {
339d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
340d30ea906Sjfb8856606 char match[MVNETA_MATCH_LEN];
341d30ea906Sjfb8856606 int ret = 0, i;
342d30ea906Sjfb8856606
343d30ea906Sjfb8856606 if (priv->ppio)
344d30ea906Sjfb8856606 return mvneta_dev_set_link_up(dev);
345d30ea906Sjfb8856606
3464418919fSjohnjiang strlcpy(match, dev->data->name, sizeof(match));
347d30ea906Sjfb8856606 priv->ppio_params.match = match;
348d30ea906Sjfb8856606 priv->ppio_params.inqs_params.mtu = dev->data->mtu;
349d30ea906Sjfb8856606
350d30ea906Sjfb8856606 ret = neta_ppio_init(&priv->ppio_params, &priv->ppio);
351d30ea906Sjfb8856606 if (ret) {
352d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to init ppio");
353d30ea906Sjfb8856606 return ret;
354d30ea906Sjfb8856606 }
355d30ea906Sjfb8856606 priv->ppio_id = priv->ppio->port_id;
356d30ea906Sjfb8856606
3574418919fSjohnjiang mvneta_stats_reset(dev);
3584418919fSjohnjiang
359d30ea906Sjfb8856606 /*
360d30ea906Sjfb8856606 * In case there are some some stale uc/mc mac addresses flush them
361d30ea906Sjfb8856606 * here. It cannot be done during mvneta_dev_close() as port information
362d30ea906Sjfb8856606 * is already gone at that point (due to neta_ppio_deinit() in
363d30ea906Sjfb8856606 * mvneta_dev_stop()).
364d30ea906Sjfb8856606 */
365d30ea906Sjfb8856606 if (!priv->uc_mc_flushed) {
366d30ea906Sjfb8856606 ret = neta_ppio_flush_mac_addrs(priv->ppio, 0, 1);
367d30ea906Sjfb8856606 if (ret) {
368d30ea906Sjfb8856606 MVNETA_LOG(ERR,
369d30ea906Sjfb8856606 "Failed to flush uc/mc filter list");
370d30ea906Sjfb8856606 goto out;
371d30ea906Sjfb8856606 }
372d30ea906Sjfb8856606 priv->uc_mc_flushed = 1;
373d30ea906Sjfb8856606 }
374d30ea906Sjfb8856606
375d30ea906Sjfb8856606 ret = mvneta_alloc_rx_bufs(dev);
376d30ea906Sjfb8856606 if (ret)
377d30ea906Sjfb8856606 goto out;
378d30ea906Sjfb8856606
379d30ea906Sjfb8856606 ret = mvneta_mtu_set(dev, dev->data->mtu);
380d30ea906Sjfb8856606 if (ret) {
381d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to set MTU %d", dev->data->mtu);
382d30ea906Sjfb8856606 goto out;
383d30ea906Sjfb8856606 }
384d30ea906Sjfb8856606
385d30ea906Sjfb8856606 ret = mvneta_dev_set_link_up(dev);
386d30ea906Sjfb8856606 if (ret) {
387d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to set link up");
388d30ea906Sjfb8856606 goto out;
389d30ea906Sjfb8856606 }
390d30ea906Sjfb8856606
391d30ea906Sjfb8856606 /* start tx queues */
392d30ea906Sjfb8856606 for (i = 0; i < dev->data->nb_tx_queues; i++)
393d30ea906Sjfb8856606 dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
394d30ea906Sjfb8856606
395d30ea906Sjfb8856606 mvneta_set_tx_function(dev);
396d30ea906Sjfb8856606
397d30ea906Sjfb8856606 return 0;
398d30ea906Sjfb8856606
399d30ea906Sjfb8856606 out:
400d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to start device");
401d30ea906Sjfb8856606 neta_ppio_deinit(priv->ppio);
402d30ea906Sjfb8856606 return ret;
403d30ea906Sjfb8856606 }
404d30ea906Sjfb8856606
405d30ea906Sjfb8856606 /**
406d30ea906Sjfb8856606 * DPDK callback to stop the device.
407d30ea906Sjfb8856606 *
408d30ea906Sjfb8856606 * @param dev
409d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
410d30ea906Sjfb8856606 */
411*2d9fd380Sjfb8856606 static int
mvneta_dev_stop(struct rte_eth_dev * dev)412d30ea906Sjfb8856606 mvneta_dev_stop(struct rte_eth_dev *dev)
413d30ea906Sjfb8856606 {
414d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
415d30ea906Sjfb8856606
416*2d9fd380Sjfb8856606 dev->data->dev_started = 0;
417*2d9fd380Sjfb8856606
418d30ea906Sjfb8856606 if (!priv->ppio)
419*2d9fd380Sjfb8856606 return 0;
420d30ea906Sjfb8856606
421d30ea906Sjfb8856606 mvneta_dev_set_link_down(dev);
422d30ea906Sjfb8856606 mvneta_flush_queues(dev);
423d30ea906Sjfb8856606 neta_ppio_deinit(priv->ppio);
424d30ea906Sjfb8856606
425d30ea906Sjfb8856606 priv->ppio = NULL;
426*2d9fd380Sjfb8856606
427*2d9fd380Sjfb8856606 return 0;
428d30ea906Sjfb8856606 }
429d30ea906Sjfb8856606
430d30ea906Sjfb8856606 /**
431d30ea906Sjfb8856606 * DPDK callback to close the device.
432d30ea906Sjfb8856606 *
433d30ea906Sjfb8856606 * @param dev
434d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
435d30ea906Sjfb8856606 */
436*2d9fd380Sjfb8856606 static int
mvneta_dev_close(struct rte_eth_dev * dev)437d30ea906Sjfb8856606 mvneta_dev_close(struct rte_eth_dev *dev)
438d30ea906Sjfb8856606 {
439d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
440*2d9fd380Sjfb8856606 int i, ret = 0;
441*2d9fd380Sjfb8856606
442*2d9fd380Sjfb8856606 if (rte_eal_process_type() != RTE_PROC_PRIMARY)
443*2d9fd380Sjfb8856606 return 0;
444d30ea906Sjfb8856606
445d30ea906Sjfb8856606 if (priv->ppio)
446*2d9fd380Sjfb8856606 ret = mvneta_dev_stop(dev);
447d30ea906Sjfb8856606
448d30ea906Sjfb8856606 for (i = 0; i < dev->data->nb_rx_queues; i++) {
449d30ea906Sjfb8856606 mvneta_rx_queue_release(dev->data->rx_queues[i]);
450d30ea906Sjfb8856606 dev->data->rx_queues[i] = NULL;
451d30ea906Sjfb8856606 }
452d30ea906Sjfb8856606
453d30ea906Sjfb8856606 for (i = 0; i < dev->data->nb_tx_queues; i++) {
454d30ea906Sjfb8856606 mvneta_tx_queue_release(dev->data->tx_queues[i]);
455d30ea906Sjfb8856606 dev->data->tx_queues[i] = NULL;
456d30ea906Sjfb8856606 }
4574418919fSjohnjiang
4584418919fSjohnjiang mvneta_dev_num--;
4594418919fSjohnjiang
4604418919fSjohnjiang if (mvneta_dev_num == 0) {
4614418919fSjohnjiang MVNETA_LOG(INFO, "Perform MUSDK deinit");
4624418919fSjohnjiang mvneta_neta_deinit();
4634418919fSjohnjiang rte_mvep_deinit(MVEP_MOD_T_NETA);
4644418919fSjohnjiang }
465*2d9fd380Sjfb8856606
466*2d9fd380Sjfb8856606 return ret;
467d30ea906Sjfb8856606 }
468d30ea906Sjfb8856606
469d30ea906Sjfb8856606 /**
470d30ea906Sjfb8856606 * DPDK callback to retrieve physical link information.
471d30ea906Sjfb8856606 *
472d30ea906Sjfb8856606 * @param dev
473d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
474d30ea906Sjfb8856606 * @param wait_to_complete
475d30ea906Sjfb8856606 * Wait for request completion (ignored).
476d30ea906Sjfb8856606 *
477d30ea906Sjfb8856606 * @return
478d30ea906Sjfb8856606 * 0 on success, negative error value otherwise.
479d30ea906Sjfb8856606 */
480d30ea906Sjfb8856606 static int
mvneta_link_update(struct rte_eth_dev * dev,int wait_to_complete __rte_unused)481d30ea906Sjfb8856606 mvneta_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
482d30ea906Sjfb8856606 {
483d30ea906Sjfb8856606 /*
484d30ea906Sjfb8856606 * TODO
485d30ea906Sjfb8856606 * once MUSDK provides necessary API use it here
486d30ea906Sjfb8856606 */
487d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
488d30ea906Sjfb8856606 struct ethtool_cmd edata;
489d30ea906Sjfb8856606 struct ifreq req;
490d30ea906Sjfb8856606 int ret, fd, link_up;
491d30ea906Sjfb8856606
492d30ea906Sjfb8856606 if (!priv->ppio)
493d30ea906Sjfb8856606 return -EPERM;
494d30ea906Sjfb8856606
495d30ea906Sjfb8856606 edata.cmd = ETHTOOL_GSET;
496d30ea906Sjfb8856606
497d30ea906Sjfb8856606 strcpy(req.ifr_name, dev->data->name);
498d30ea906Sjfb8856606 req.ifr_data = (void *)&edata;
499d30ea906Sjfb8856606
500d30ea906Sjfb8856606 fd = socket(AF_INET, SOCK_DGRAM, 0);
501d30ea906Sjfb8856606 if (fd == -1)
502d30ea906Sjfb8856606 return -EFAULT;
503d30ea906Sjfb8856606 ret = ioctl(fd, SIOCETHTOOL, &req);
504d30ea906Sjfb8856606 if (ret == -1) {
505d30ea906Sjfb8856606 close(fd);
506d30ea906Sjfb8856606 return -EFAULT;
507d30ea906Sjfb8856606 }
508d30ea906Sjfb8856606
509d30ea906Sjfb8856606 close(fd);
510d30ea906Sjfb8856606
511d30ea906Sjfb8856606 switch (ethtool_cmd_speed(&edata)) {
512d30ea906Sjfb8856606 case SPEED_10:
513d30ea906Sjfb8856606 dev->data->dev_link.link_speed = ETH_SPEED_NUM_10M;
514d30ea906Sjfb8856606 break;
515d30ea906Sjfb8856606 case SPEED_100:
516d30ea906Sjfb8856606 dev->data->dev_link.link_speed = ETH_SPEED_NUM_100M;
517d30ea906Sjfb8856606 break;
518d30ea906Sjfb8856606 case SPEED_1000:
519d30ea906Sjfb8856606 dev->data->dev_link.link_speed = ETH_SPEED_NUM_1G;
520d30ea906Sjfb8856606 break;
521d30ea906Sjfb8856606 case SPEED_2500:
522d30ea906Sjfb8856606 dev->data->dev_link.link_speed = ETH_SPEED_NUM_2_5G;
523d30ea906Sjfb8856606 break;
524d30ea906Sjfb8856606 default:
525d30ea906Sjfb8856606 dev->data->dev_link.link_speed = ETH_SPEED_NUM_NONE;
526d30ea906Sjfb8856606 }
527d30ea906Sjfb8856606
528d30ea906Sjfb8856606 dev->data->dev_link.link_duplex = edata.duplex ? ETH_LINK_FULL_DUPLEX :
529d30ea906Sjfb8856606 ETH_LINK_HALF_DUPLEX;
530d30ea906Sjfb8856606 dev->data->dev_link.link_autoneg = edata.autoneg ? ETH_LINK_AUTONEG :
531d30ea906Sjfb8856606 ETH_LINK_FIXED;
532d30ea906Sjfb8856606
533d30ea906Sjfb8856606 neta_ppio_get_link_state(priv->ppio, &link_up);
534d30ea906Sjfb8856606 dev->data->dev_link.link_status = link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
535d30ea906Sjfb8856606
536d30ea906Sjfb8856606 return 0;
537d30ea906Sjfb8856606 }
538d30ea906Sjfb8856606
539d30ea906Sjfb8856606 /**
540d30ea906Sjfb8856606 * DPDK callback to enable promiscuous mode.
541d30ea906Sjfb8856606 *
542d30ea906Sjfb8856606 * @param dev
543d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
5444418919fSjohnjiang *
5454418919fSjohnjiang * @return
5464418919fSjohnjiang * always 0
547d30ea906Sjfb8856606 */
5484418919fSjohnjiang static int
mvneta_promiscuous_enable(struct rte_eth_dev * dev)549d30ea906Sjfb8856606 mvneta_promiscuous_enable(struct rte_eth_dev *dev)
550d30ea906Sjfb8856606 {
551d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
552d30ea906Sjfb8856606 int ret, en;
553d30ea906Sjfb8856606
554d30ea906Sjfb8856606 if (!priv->ppio)
5554418919fSjohnjiang return 0;
556d30ea906Sjfb8856606
557d30ea906Sjfb8856606 neta_ppio_get_promisc(priv->ppio, &en);
558d30ea906Sjfb8856606 if (en) {
559d30ea906Sjfb8856606 MVNETA_LOG(INFO, "Promiscuous already enabled");
5604418919fSjohnjiang return 0;
561d30ea906Sjfb8856606 }
562d30ea906Sjfb8856606
563d30ea906Sjfb8856606 ret = neta_ppio_set_promisc(priv->ppio, 1);
564d30ea906Sjfb8856606 if (ret)
565d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to enable promiscuous mode");
5664418919fSjohnjiang
5674418919fSjohnjiang return 0;
568d30ea906Sjfb8856606 }
569d30ea906Sjfb8856606
570d30ea906Sjfb8856606 /**
571d30ea906Sjfb8856606 * DPDK callback to disable allmulticast mode.
572d30ea906Sjfb8856606 *
573d30ea906Sjfb8856606 * @param dev
574d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
5754418919fSjohnjiang *
5764418919fSjohnjiang * @return
5774418919fSjohnjiang * always 0
578d30ea906Sjfb8856606 */
5794418919fSjohnjiang static int
mvneta_promiscuous_disable(struct rte_eth_dev * dev)580d30ea906Sjfb8856606 mvneta_promiscuous_disable(struct rte_eth_dev *dev)
581d30ea906Sjfb8856606 {
582d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
583d30ea906Sjfb8856606 int ret, en;
584d30ea906Sjfb8856606
585d30ea906Sjfb8856606 if (!priv->ppio)
5864418919fSjohnjiang return 0;
587d30ea906Sjfb8856606
588d30ea906Sjfb8856606 neta_ppio_get_promisc(priv->ppio, &en);
589d30ea906Sjfb8856606 if (!en) {
590d30ea906Sjfb8856606 MVNETA_LOG(INFO, "Promiscuous already disabled");
5914418919fSjohnjiang return 0;
592d30ea906Sjfb8856606 }
593d30ea906Sjfb8856606
594d30ea906Sjfb8856606 ret = neta_ppio_set_promisc(priv->ppio, 0);
595d30ea906Sjfb8856606 if (ret)
596d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to disable promiscuous mode");
5974418919fSjohnjiang
5984418919fSjohnjiang return 0;
599d30ea906Sjfb8856606 }
600d30ea906Sjfb8856606
601d30ea906Sjfb8856606 /**
602d30ea906Sjfb8856606 * DPDK callback to remove a MAC address.
603d30ea906Sjfb8856606 *
604d30ea906Sjfb8856606 * @param dev
605d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
606d30ea906Sjfb8856606 * @param index
607d30ea906Sjfb8856606 * MAC address index.
608d30ea906Sjfb8856606 */
609d30ea906Sjfb8856606 static void
mvneta_mac_addr_remove(struct rte_eth_dev * dev,uint32_t index)610d30ea906Sjfb8856606 mvneta_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
611d30ea906Sjfb8856606 {
612d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
6134418919fSjohnjiang char buf[RTE_ETHER_ADDR_FMT_SIZE];
614d30ea906Sjfb8856606 int ret;
615d30ea906Sjfb8856606
616d30ea906Sjfb8856606 if (!priv->ppio)
617d30ea906Sjfb8856606 return;
618d30ea906Sjfb8856606
619d30ea906Sjfb8856606 ret = neta_ppio_remove_mac_addr(priv->ppio,
620d30ea906Sjfb8856606 dev->data->mac_addrs[index].addr_bytes);
621d30ea906Sjfb8856606 if (ret) {
6224418919fSjohnjiang rte_ether_format_addr(buf, sizeof(buf),
623d30ea906Sjfb8856606 &dev->data->mac_addrs[index]);
624d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to remove mac %s", buf);
625d30ea906Sjfb8856606 }
626d30ea906Sjfb8856606 }
627d30ea906Sjfb8856606
628d30ea906Sjfb8856606 /**
629d30ea906Sjfb8856606 * DPDK callback to add a MAC address.
630d30ea906Sjfb8856606 *
631d30ea906Sjfb8856606 * @param dev
632d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
633d30ea906Sjfb8856606 * @param mac_addr
634d30ea906Sjfb8856606 * MAC address to register.
635d30ea906Sjfb8856606 * @param index
636d30ea906Sjfb8856606 * MAC address index.
637d30ea906Sjfb8856606 * @param vmdq
638d30ea906Sjfb8856606 * VMDq pool index to associate address with (unused).
639d30ea906Sjfb8856606 *
640d30ea906Sjfb8856606 * @return
641d30ea906Sjfb8856606 * 0 on success, negative error value otherwise.
642d30ea906Sjfb8856606 */
643d30ea906Sjfb8856606 static int
mvneta_mac_addr_add(struct rte_eth_dev * dev,struct rte_ether_addr * mac_addr,uint32_t index,uint32_t vmdq __rte_unused)6444418919fSjohnjiang mvneta_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
645d30ea906Sjfb8856606 uint32_t index, uint32_t vmdq __rte_unused)
646d30ea906Sjfb8856606 {
647d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
6484418919fSjohnjiang char buf[RTE_ETHER_ADDR_FMT_SIZE];
649d30ea906Sjfb8856606 int ret;
650d30ea906Sjfb8856606
651d30ea906Sjfb8856606 if (index == 0)
652d30ea906Sjfb8856606 /* For setting index 0, mrvl_mac_addr_set() should be used.*/
653d30ea906Sjfb8856606 return -1;
654d30ea906Sjfb8856606
655d30ea906Sjfb8856606 if (!priv->ppio)
656d30ea906Sjfb8856606 return 0;
657d30ea906Sjfb8856606
658d30ea906Sjfb8856606 ret = neta_ppio_add_mac_addr(priv->ppio, mac_addr->addr_bytes);
659d30ea906Sjfb8856606 if (ret) {
6604418919fSjohnjiang rte_ether_format_addr(buf, sizeof(buf), mac_addr);
661d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to add mac %s", buf);
662d30ea906Sjfb8856606 return -1;
663d30ea906Sjfb8856606 }
664d30ea906Sjfb8856606
665d30ea906Sjfb8856606 return 0;
666d30ea906Sjfb8856606 }
667d30ea906Sjfb8856606
668d30ea906Sjfb8856606 /**
669d30ea906Sjfb8856606 * DPDK callback to set the primary MAC address.
670d30ea906Sjfb8856606 *
671d30ea906Sjfb8856606 * @param dev
672d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
673d30ea906Sjfb8856606 * @param mac_addr
674d30ea906Sjfb8856606 * MAC address to register.
675d30ea906Sjfb8856606 */
676d30ea906Sjfb8856606 static int
mvneta_mac_addr_set(struct rte_eth_dev * dev,struct rte_ether_addr * mac_addr)6774418919fSjohnjiang mvneta_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
678d30ea906Sjfb8856606 {
679d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
680d30ea906Sjfb8856606 int ret;
681d30ea906Sjfb8856606
682d30ea906Sjfb8856606 if (!priv->ppio)
683d30ea906Sjfb8856606 return -EINVAL;
684d30ea906Sjfb8856606
685d30ea906Sjfb8856606 ret = neta_ppio_set_mac_addr(priv->ppio, mac_addr->addr_bytes);
686d30ea906Sjfb8856606 if (ret) {
6874418919fSjohnjiang char buf[RTE_ETHER_ADDR_FMT_SIZE];
6884418919fSjohnjiang rte_ether_format_addr(buf, sizeof(buf), mac_addr);
689d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to set mac to %s", buf);
690d30ea906Sjfb8856606 }
691d30ea906Sjfb8856606 return 0;
692d30ea906Sjfb8856606 }
693d30ea906Sjfb8856606
694d30ea906Sjfb8856606 /**
695d30ea906Sjfb8856606 * DPDK callback to get device statistics.
696d30ea906Sjfb8856606 *
697d30ea906Sjfb8856606 * @param dev
698d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
699d30ea906Sjfb8856606 * @param stats
700d30ea906Sjfb8856606 * Stats structure output buffer.
701d30ea906Sjfb8856606 *
702d30ea906Sjfb8856606 * @return
703d30ea906Sjfb8856606 * 0 on success, negative error value otherwise.
704d30ea906Sjfb8856606 */
705d30ea906Sjfb8856606 static int
mvneta_stats_get(struct rte_eth_dev * dev,struct rte_eth_stats * stats)706d30ea906Sjfb8856606 mvneta_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
707d30ea906Sjfb8856606 {
708d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
709d30ea906Sjfb8856606 struct neta_ppio_statistics ppio_stats;
710d30ea906Sjfb8856606 unsigned int ret;
711d30ea906Sjfb8856606
712d30ea906Sjfb8856606 if (!priv->ppio)
713d30ea906Sjfb8856606 return -EPERM;
714d30ea906Sjfb8856606
715d30ea906Sjfb8856606 ret = neta_ppio_get_statistics(priv->ppio, &ppio_stats);
716d30ea906Sjfb8856606 if (unlikely(ret)) {
717d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to update port statistics");
718d30ea906Sjfb8856606 return ret;
719d30ea906Sjfb8856606 }
720d30ea906Sjfb8856606
721d30ea906Sjfb8856606 stats->ipackets += ppio_stats.rx_packets +
722d30ea906Sjfb8856606 ppio_stats.rx_broadcast_packets +
723d30ea906Sjfb8856606 ppio_stats.rx_multicast_packets -
724d30ea906Sjfb8856606 priv->prev_stats.ipackets;
725d30ea906Sjfb8856606 stats->opackets += ppio_stats.tx_packets +
726d30ea906Sjfb8856606 ppio_stats.tx_broadcast_packets +
727d30ea906Sjfb8856606 ppio_stats.tx_multicast_packets -
728d30ea906Sjfb8856606 priv->prev_stats.opackets;
729d30ea906Sjfb8856606 stats->ibytes += ppio_stats.rx_bytes - priv->prev_stats.ibytes;
730d30ea906Sjfb8856606 stats->obytes += ppio_stats.tx_bytes - priv->prev_stats.obytes;
731d30ea906Sjfb8856606 stats->imissed += ppio_stats.rx_discard +
732d30ea906Sjfb8856606 ppio_stats.rx_overrun -
733d30ea906Sjfb8856606 priv->prev_stats.imissed;
7344b05018fSfengbojiang stats->ierrors = ppio_stats.rx_packets_err -
735d30ea906Sjfb8856606 priv->prev_stats.ierrors;
736d30ea906Sjfb8856606 stats->oerrors = ppio_stats.tx_errors - priv->prev_stats.oerrors;
737d30ea906Sjfb8856606
738d30ea906Sjfb8856606 return 0;
739d30ea906Sjfb8856606 }
740d30ea906Sjfb8856606
741d30ea906Sjfb8856606 /**
742d30ea906Sjfb8856606 * DPDK callback to clear device statistics.
743d30ea906Sjfb8856606 *
744d30ea906Sjfb8856606 * @param dev
745d30ea906Sjfb8856606 * Pointer to Ethernet device structure.
7464418919fSjohnjiang *
7474418919fSjohnjiang * @return
7484418919fSjohnjiang * 0 on success, negative error value otherwise.
749d30ea906Sjfb8856606 */
7504418919fSjohnjiang static int
mvneta_stats_reset(struct rte_eth_dev * dev)751d30ea906Sjfb8856606 mvneta_stats_reset(struct rte_eth_dev *dev)
752d30ea906Sjfb8856606 {
753d30ea906Sjfb8856606 struct mvneta_priv *priv = dev->data->dev_private;
754d30ea906Sjfb8856606 unsigned int ret;
755d30ea906Sjfb8856606
756d30ea906Sjfb8856606 if (!priv->ppio)
7574418919fSjohnjiang return 0;
758d30ea906Sjfb8856606
759d30ea906Sjfb8856606 ret = mvneta_stats_get(dev, &priv->prev_stats);
760d30ea906Sjfb8856606 if (unlikely(ret))
7610c6bd470Sfengbojiang MVNETA_LOG(ERR, "Failed to reset port statistics");
7624418919fSjohnjiang
7634418919fSjohnjiang return ret;
764d30ea906Sjfb8856606 }
765d30ea906Sjfb8856606
766d30ea906Sjfb8856606
767d30ea906Sjfb8856606 static const struct eth_dev_ops mvneta_ops = {
768d30ea906Sjfb8856606 .dev_configure = mvneta_dev_configure,
769d30ea906Sjfb8856606 .dev_start = mvneta_dev_start,
770d30ea906Sjfb8856606 .dev_stop = mvneta_dev_stop,
771d30ea906Sjfb8856606 .dev_set_link_up = mvneta_dev_set_link_up,
772d30ea906Sjfb8856606 .dev_set_link_down = mvneta_dev_set_link_down,
773d30ea906Sjfb8856606 .dev_close = mvneta_dev_close,
774d30ea906Sjfb8856606 .link_update = mvneta_link_update,
775d30ea906Sjfb8856606 .promiscuous_enable = mvneta_promiscuous_enable,
776d30ea906Sjfb8856606 .promiscuous_disable = mvneta_promiscuous_disable,
777d30ea906Sjfb8856606 .mac_addr_remove = mvneta_mac_addr_remove,
778d30ea906Sjfb8856606 .mac_addr_add = mvneta_mac_addr_add,
779d30ea906Sjfb8856606 .mac_addr_set = mvneta_mac_addr_set,
780d30ea906Sjfb8856606 .mtu_set = mvneta_mtu_set,
781d30ea906Sjfb8856606 .stats_get = mvneta_stats_get,
782d30ea906Sjfb8856606 .stats_reset = mvneta_stats_reset,
783d30ea906Sjfb8856606 .dev_infos_get = mvneta_dev_infos_get,
784d30ea906Sjfb8856606 .dev_supported_ptypes_get = mvneta_dev_supported_ptypes_get,
785d30ea906Sjfb8856606 .rxq_info_get = mvneta_rxq_info_get,
786d30ea906Sjfb8856606 .txq_info_get = mvneta_txq_info_get,
787d30ea906Sjfb8856606 .rx_queue_setup = mvneta_rx_queue_setup,
788d30ea906Sjfb8856606 .rx_queue_release = mvneta_rx_queue_release,
789d30ea906Sjfb8856606 .tx_queue_setup = mvneta_tx_queue_setup,
790d30ea906Sjfb8856606 .tx_queue_release = mvneta_tx_queue_release,
791d30ea906Sjfb8856606 };
792d30ea906Sjfb8856606
793d30ea906Sjfb8856606 /**
794d30ea906Sjfb8856606 * Create device representing Ethernet port.
795d30ea906Sjfb8856606 *
796d30ea906Sjfb8856606 * @param name
797d30ea906Sjfb8856606 * Pointer to the port's name.
798d30ea906Sjfb8856606 *
799d30ea906Sjfb8856606 * @return
800d30ea906Sjfb8856606 * 0 on success, negative error value otherwise.
801d30ea906Sjfb8856606 */
802d30ea906Sjfb8856606 static int
mvneta_eth_dev_create(struct rte_vdev_device * vdev,const char * name)803d30ea906Sjfb8856606 mvneta_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
804d30ea906Sjfb8856606 {
805d30ea906Sjfb8856606 int ret, fd = socket(AF_INET, SOCK_DGRAM, 0);
806d30ea906Sjfb8856606 struct rte_eth_dev *eth_dev;
807d30ea906Sjfb8856606 struct mvneta_priv *priv;
808d30ea906Sjfb8856606 struct ifreq req;
809d30ea906Sjfb8856606
810d30ea906Sjfb8856606 eth_dev = rte_eth_dev_allocate(name);
811d30ea906Sjfb8856606 if (!eth_dev)
812d30ea906Sjfb8856606 return -ENOMEM;
813d30ea906Sjfb8856606
814d30ea906Sjfb8856606 priv = rte_zmalloc_socket(name, sizeof(*priv), 0, rte_socket_id());
815d30ea906Sjfb8856606 if (!priv) {
816d30ea906Sjfb8856606 ret = -ENOMEM;
817d30ea906Sjfb8856606 goto out_free;
818d30ea906Sjfb8856606 }
819d30ea906Sjfb8856606 eth_dev->data->dev_private = priv;
820d30ea906Sjfb8856606
821d30ea906Sjfb8856606 eth_dev->data->mac_addrs =
822d30ea906Sjfb8856606 rte_zmalloc("mac_addrs",
8234418919fSjohnjiang RTE_ETHER_ADDR_LEN * MVNETA_MAC_ADDRS_MAX, 0);
824d30ea906Sjfb8856606 if (!eth_dev->data->mac_addrs) {
825d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to allocate space for eth addrs");
826d30ea906Sjfb8856606 ret = -ENOMEM;
827d30ea906Sjfb8856606 goto out_free;
828d30ea906Sjfb8856606 }
829d30ea906Sjfb8856606
830d30ea906Sjfb8856606 memset(&req, 0, sizeof(req));
831d30ea906Sjfb8856606 strcpy(req.ifr_name, name);
832d30ea906Sjfb8856606 ret = ioctl(fd, SIOCGIFHWADDR, &req);
833d30ea906Sjfb8856606 if (ret)
834d30ea906Sjfb8856606 goto out_free;
835d30ea906Sjfb8856606
836d30ea906Sjfb8856606 memcpy(eth_dev->data->mac_addrs[0].addr_bytes,
8374418919fSjohnjiang req.ifr_addr.sa_data, RTE_ETHER_ADDR_LEN);
838d30ea906Sjfb8856606
839d30ea906Sjfb8856606 eth_dev->device = &vdev->device;
840d30ea906Sjfb8856606 eth_dev->rx_pkt_burst = mvneta_rx_pkt_burst;
841d30ea906Sjfb8856606 mvneta_set_tx_function(eth_dev);
842d30ea906Sjfb8856606 eth_dev->dev_ops = &mvneta_ops;
843*2d9fd380Sjfb8856606 eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
8444418919fSjohnjiang
845d30ea906Sjfb8856606 rte_eth_dev_probing_finish(eth_dev);
846d30ea906Sjfb8856606 return 0;
847d30ea906Sjfb8856606 out_free:
848d30ea906Sjfb8856606 rte_eth_dev_release_port(eth_dev);
849d30ea906Sjfb8856606
850d30ea906Sjfb8856606 return ret;
851d30ea906Sjfb8856606 }
852d30ea906Sjfb8856606
853d30ea906Sjfb8856606 /**
854d30ea906Sjfb8856606 * Cleanup previously created device representing Ethernet port.
855d30ea906Sjfb8856606 *
856d30ea906Sjfb8856606 * @param eth_dev
857d30ea906Sjfb8856606 * Pointer to the corresponding rte_eth_dev structure.
858d30ea906Sjfb8856606 */
859d30ea906Sjfb8856606 static void
mvneta_eth_dev_destroy(struct rte_eth_dev * eth_dev)860d30ea906Sjfb8856606 mvneta_eth_dev_destroy(struct rte_eth_dev *eth_dev)
861d30ea906Sjfb8856606 {
862d30ea906Sjfb8856606 rte_eth_dev_release_port(eth_dev);
863d30ea906Sjfb8856606 }
864d30ea906Sjfb8856606
865d30ea906Sjfb8856606 /**
866d30ea906Sjfb8856606 * Cleanup previously created device representing Ethernet port.
867d30ea906Sjfb8856606 *
868d30ea906Sjfb8856606 * @param name
869d30ea906Sjfb8856606 * Pointer to the port name.
870d30ea906Sjfb8856606 */
871d30ea906Sjfb8856606 static void
mvneta_eth_dev_destroy_name(const char * name)872d30ea906Sjfb8856606 mvneta_eth_dev_destroy_name(const char *name)
873d30ea906Sjfb8856606 {
874d30ea906Sjfb8856606 struct rte_eth_dev *eth_dev;
875d30ea906Sjfb8856606
876d30ea906Sjfb8856606 eth_dev = rte_eth_dev_allocated(name);
877d30ea906Sjfb8856606 if (!eth_dev)
878d30ea906Sjfb8856606 return;
879d30ea906Sjfb8856606
880d30ea906Sjfb8856606 mvneta_eth_dev_destroy(eth_dev);
881d30ea906Sjfb8856606 }
882d30ea906Sjfb8856606
883d30ea906Sjfb8856606 /**
884d30ea906Sjfb8856606 * DPDK callback to register the virtual device.
885d30ea906Sjfb8856606 *
886d30ea906Sjfb8856606 * @param vdev
887d30ea906Sjfb8856606 * Pointer to the virtual device.
888d30ea906Sjfb8856606 *
889d30ea906Sjfb8856606 * @return
890d30ea906Sjfb8856606 * 0 on success, negative error value otherwise.
891d30ea906Sjfb8856606 */
892d30ea906Sjfb8856606 static int
rte_pmd_mvneta_probe(struct rte_vdev_device * vdev)893d30ea906Sjfb8856606 rte_pmd_mvneta_probe(struct rte_vdev_device *vdev)
894d30ea906Sjfb8856606 {
895d30ea906Sjfb8856606 struct rte_kvargs *kvlist;
896d30ea906Sjfb8856606 struct mvneta_ifnames ifnames;
897d30ea906Sjfb8856606 int ret = -EINVAL;
898d30ea906Sjfb8856606 uint32_t i, ifnum;
899d30ea906Sjfb8856606 const char *params;
900d30ea906Sjfb8856606
901d30ea906Sjfb8856606 params = rte_vdev_device_args(vdev);
902d30ea906Sjfb8856606 if (!params)
903d30ea906Sjfb8856606 return -EINVAL;
904d30ea906Sjfb8856606
905d30ea906Sjfb8856606 kvlist = rte_kvargs_parse(params, valid_args);
906d30ea906Sjfb8856606 if (!kvlist)
907d30ea906Sjfb8856606 return -EINVAL;
908d30ea906Sjfb8856606
909d30ea906Sjfb8856606 ifnum = rte_kvargs_count(kvlist, MVNETA_IFACE_NAME_ARG);
910d30ea906Sjfb8856606 if (ifnum > RTE_DIM(ifnames.names))
911d30ea906Sjfb8856606 goto out_free_kvlist;
912d30ea906Sjfb8856606
913d30ea906Sjfb8856606 ifnames.idx = 0;
914d30ea906Sjfb8856606 rte_kvargs_process(kvlist, MVNETA_IFACE_NAME_ARG,
915d30ea906Sjfb8856606 mvneta_ifnames_get, &ifnames);
916d30ea906Sjfb8856606
917d30ea906Sjfb8856606 /*
918d30ea906Sjfb8856606 * The below system initialization should be done only once,
919d30ea906Sjfb8856606 * on the first provided configuration file
920d30ea906Sjfb8856606 */
921d30ea906Sjfb8856606 if (mvneta_dev_num)
922d30ea906Sjfb8856606 goto init_devices;
923d30ea906Sjfb8856606
924d30ea906Sjfb8856606 MVNETA_LOG(INFO, "Perform MUSDK initializations");
925d30ea906Sjfb8856606
926d30ea906Sjfb8856606 ret = rte_mvep_init(MVEP_MOD_T_NETA, kvlist);
927d30ea906Sjfb8856606 if (ret)
928d30ea906Sjfb8856606 goto out_free_kvlist;
929d30ea906Sjfb8856606
930d30ea906Sjfb8856606 ret = mvneta_neta_init();
931d30ea906Sjfb8856606 if (ret) {
932d30ea906Sjfb8856606 MVNETA_LOG(ERR, "Failed to init NETA!");
933d30ea906Sjfb8856606 rte_mvep_deinit(MVEP_MOD_T_NETA);
934d30ea906Sjfb8856606 goto out_free_kvlist;
935d30ea906Sjfb8856606 }
936d30ea906Sjfb8856606
937d30ea906Sjfb8856606 init_devices:
938d30ea906Sjfb8856606 for (i = 0; i < ifnum; i++) {
939d30ea906Sjfb8856606 MVNETA_LOG(INFO, "Creating %s", ifnames.names[i]);
940d30ea906Sjfb8856606 ret = mvneta_eth_dev_create(vdev, ifnames.names[i]);
941d30ea906Sjfb8856606 if (ret)
942d30ea906Sjfb8856606 goto out_cleanup;
9434418919fSjohnjiang
9444418919fSjohnjiang mvneta_dev_num++;
945d30ea906Sjfb8856606 }
946d30ea906Sjfb8856606
947d30ea906Sjfb8856606 rte_kvargs_free(kvlist);
948d30ea906Sjfb8856606
949d30ea906Sjfb8856606 return 0;
950d30ea906Sjfb8856606 out_cleanup:
9514418919fSjohnjiang rte_pmd_mvneta_remove(vdev);
952d30ea906Sjfb8856606
953d30ea906Sjfb8856606 out_free_kvlist:
954d30ea906Sjfb8856606 rte_kvargs_free(kvlist);
955d30ea906Sjfb8856606
956d30ea906Sjfb8856606 return ret;
957d30ea906Sjfb8856606 }
958d30ea906Sjfb8856606
959d30ea906Sjfb8856606 /**
960d30ea906Sjfb8856606 * DPDK callback to remove virtual device.
961d30ea906Sjfb8856606 *
962d30ea906Sjfb8856606 * @param vdev
963d30ea906Sjfb8856606 * Pointer to the removed virtual device.
964d30ea906Sjfb8856606 *
965d30ea906Sjfb8856606 * @return
966d30ea906Sjfb8856606 * 0 on success, negative error value otherwise.
967d30ea906Sjfb8856606 */
968d30ea906Sjfb8856606 static int
rte_pmd_mvneta_remove(struct rte_vdev_device * vdev)969d30ea906Sjfb8856606 rte_pmd_mvneta_remove(struct rte_vdev_device *vdev)
970d30ea906Sjfb8856606 {
9714418919fSjohnjiang uint16_t port_id;
972*2d9fd380Sjfb8856606 int ret = 0;
973d30ea906Sjfb8856606
9744418919fSjohnjiang RTE_ETH_FOREACH_DEV(port_id) {
9754418919fSjohnjiang if (rte_eth_devices[port_id].device != &vdev->device)
976d30ea906Sjfb8856606 continue;
977*2d9fd380Sjfb8856606 ret |= rte_eth_dev_close(port_id);
978d30ea906Sjfb8856606 }
979d30ea906Sjfb8856606
980*2d9fd380Sjfb8856606 return ret == 0 ? 0 : -EIO;
981d30ea906Sjfb8856606 }
982d30ea906Sjfb8856606
983d30ea906Sjfb8856606 static struct rte_vdev_driver pmd_mvneta_drv = {
984d30ea906Sjfb8856606 .probe = rte_pmd_mvneta_probe,
985d30ea906Sjfb8856606 .remove = rte_pmd_mvneta_remove,
986d30ea906Sjfb8856606 };
987d30ea906Sjfb8856606
988d30ea906Sjfb8856606 RTE_PMD_REGISTER_VDEV(net_mvneta, pmd_mvneta_drv);
989d30ea906Sjfb8856606 RTE_PMD_REGISTER_PARAM_STRING(net_mvneta, "iface=<ifc>");
990*2d9fd380Sjfb8856606 RTE_LOG_REGISTER(mvneta_logtype, pmd.net.mvneta, NOTICE);
991