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