dpdk/drivers/net/mvneta/mvneta_ethdev.c
<<
>>
Prefs
   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 <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
  37static const char * const valid_args[] = {
  38        MVNETA_IFACE_NAME_ARG,
  39        NULL
  40};
  41
  42struct mvneta_ifnames {
  43        const char *names[NETA_NUM_ETH_PPIO];
  44        int idx;
  45};
  46
  47static int mvneta_dev_num;
  48
  49static int mvneta_stats_reset(struct rte_eth_dev *dev);
  50static int rte_pmd_mvneta_remove(struct rte_vdev_device *vdev);
  51
  52
  53/**
  54 * Deinitialize packet processor.
  55 */
  56static void
  57mvneta_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 */
  68static int
  69mvneta_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 */
  88static int
  89mvneta_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 */
 111static int
 112mvneta_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 */
 154static int
 155mvneta_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 */
 201static const uint32_t *
 202mvneta_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 */
 230static int
 231mvneta_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 */
 296static int
 297mvneta_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 */
 316static int
 317mvneta_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 */
 336static int
 337mvneta_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
 399out:
 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 */
 411static int
 412mvneta_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 */
 436static int
 437mvneta_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 */
 480static int
 481mvneta_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 */
 548static int
 549mvneta_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 */
 579static int
 580mvneta_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 */
 609static void
 610mvneta_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 */
 643static int
 644mvneta_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 */
 676static int
 677mvneta_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 */
 705static int
 706mvneta_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 */
 750static int
 751mvneta_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
 767static 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 */
 802static int
 803mvneta_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;
 847out_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 */
 859static void
 860mvneta_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 */
 871static void
 872mvneta_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 */
 892static int
 893rte_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
 937init_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;
 950out_cleanup:
 951        rte_pmd_mvneta_remove(vdev);
 952
 953out_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 */
 968static int
 969rte_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
 983static struct rte_vdev_driver pmd_mvneta_drv = {
 984        .probe = rte_pmd_mvneta_probe,
 985        .remove = rte_pmd_mvneta_remove,
 986};
 987
 988RTE_PMD_REGISTER_VDEV(net_mvneta, pmd_mvneta_drv);
 989RTE_PMD_REGISTER_PARAM_STRING(net_mvneta, "iface=<ifc>");
 990RTE_LOG_REGISTER(mvneta_logtype, pmd.net.mvneta, NOTICE);
 991