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