New upstream version 18.05
[deb_dpdk.git] / drivers / net / mvpp2 / mrvl_ethdev.c
similarity index 87%
rename from drivers/net/mrvl/mrvl_ethdev.c
rename to drivers/net/mvpp2/mrvl_ethdev.c
index 705c4bd..ea6a786 100644 (file)
@@ -1,35 +1,7 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2017 Marvell International Ltd.
- *   Copyright(c) 2017 Semihalf.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Semihalf nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Marvell International Ltd.
+ * Copyright(c) 2017 Semihalf.
+ * All rights reserved.
  */
 
 #include <rte_ethdev_driver.h>
@@ -162,6 +134,7 @@ struct mrvl_txq {
        int port_id;
        uint64_t bytes_sent;
        struct mrvl_shadow_txq shadow_txqs[RTE_MAX_LCORE];
+       int tx_deferred_start;
 };
 
 static int mrvl_lcore_first;
@@ -173,6 +146,32 @@ static inline void mrvl_free_sent_buffers(struct pp2_ppio *ppio,
                        struct pp2_hif *hif, unsigned int core_id,
                        struct mrvl_shadow_txq *sq, int qid, int force);
 
+#define MRVL_XSTATS_TBL_ENTRY(name) { \
+       #name, offsetof(struct pp2_ppio_statistics, name),      \
+       sizeof(((struct pp2_ppio_statistics *)0)->name)         \
+}
+
+/* Table with xstats data */
+static struct {
+       const char *name;
+       unsigned int offset;
+       unsigned int size;
+} mrvl_xstats_tbl[] = {
+       MRVL_XSTATS_TBL_ENTRY(rx_bytes),
+       MRVL_XSTATS_TBL_ENTRY(rx_packets),
+       MRVL_XSTATS_TBL_ENTRY(rx_unicast_packets),
+       MRVL_XSTATS_TBL_ENTRY(rx_errors),
+       MRVL_XSTATS_TBL_ENTRY(rx_fullq_dropped),
+       MRVL_XSTATS_TBL_ENTRY(rx_bm_dropped),
+       MRVL_XSTATS_TBL_ENTRY(rx_early_dropped),
+       MRVL_XSTATS_TBL_ENTRY(rx_fifo_dropped),
+       MRVL_XSTATS_TBL_ENTRY(rx_cls_dropped),
+       MRVL_XSTATS_TBL_ENTRY(tx_bytes),
+       MRVL_XSTATS_TBL_ENTRY(tx_packets),
+       MRVL_XSTATS_TBL_ENTRY(tx_unicast_packets),
+       MRVL_XSTATS_TBL_ENTRY(tx_errors)
+};
+
 static inline int
 mrvl_get_bpool_size(int pp2_id, int pool_id)
 {
@@ -319,26 +318,11 @@ mrvl_dev_configure(struct rte_eth_dev *dev)
                dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CRC_STRIP;
        }
 
-       if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_VLAN_STRIP) {
-               RTE_LOG(INFO, PMD, "VLAN stripping not supported\n");
-               return -EINVAL;
-       }
-
        if (dev->data->dev_conf.rxmode.split_hdr_size) {
                RTE_LOG(INFO, PMD, "Split headers not supported\n");
                return -EINVAL;
        }
 
-       if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_SCATTER) {
-               RTE_LOG(INFO, PMD, "RX Scatter/Gather not supported\n");
-               return -EINVAL;
-       }
-
-       if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_TCP_LRO) {
-               RTE_LOG(INFO, PMD, "LRO not supported\n");
-               return -EINVAL;
-       }
-
        if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME)
                dev->data->mtu = dev->data->dev_conf.rxmode.max_rx_pkt_len -
                                 ETHER_HDR_LEN - ETHER_CRC_LEN;
@@ -348,6 +332,11 @@ mrvl_dev_configure(struct rte_eth_dev *dev)
        if (ret < 0)
                return ret;
 
+       ret = mrvl_configure_txqs(priv, dev->data->port_id,
+                                 dev->data->nb_tx_queues);
+       if (ret < 0)
+               return ret;
+
        priv->ppio_params.outqs_params.num_outqs = dev->data->nb_tx_queues;
        priv->ppio_params.maintain_stats = 1;
        priv->nb_rx_queues = dev->data->nb_rx_queues;
@@ -455,6 +444,70 @@ mrvl_dev_set_link_down(struct rte_eth_dev *dev)
        return pp2_ppio_disable(priv->ppio);
 }
 
+/**
+ * DPDK callback to start tx queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param queue_id
+ *   Transmit queue index.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mrvl_tx_queue_start(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+       struct mrvl_priv *priv = dev->data->dev_private;
+       int ret;
+
+       if (!priv)
+               return -EPERM;
+
+       /* passing 1 enables given tx queue */
+       ret = pp2_ppio_set_outq_state(priv->ppio, queue_id, 1);
+       if (ret) {
+               RTE_LOG(ERR, PMD, "Failed to start txq %d\n", queue_id);
+               return ret;
+       }
+
+       dev->data->tx_queue_state[queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
+
+       return 0;
+}
+
+/**
+ * DPDK callback to stop tx queue.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param queue_id
+ *   Transmit queue index.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mrvl_tx_queue_stop(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+       struct mrvl_priv *priv = dev->data->dev_private;
+       int ret;
+
+       if (!priv->ppio)
+               return -EPERM;
+
+       /* passing 0 disables given tx queue */
+       ret = pp2_ppio_set_outq_state(priv->ppio, queue_id, 0);
+       if (ret) {
+               RTE_LOG(ERR, PMD, "Failed to stop txq %d\n", queue_id);
+               return ret;
+       }
+
+       dev->data->tx_queue_state[queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
+
+       return 0;
+}
+
 /**
  * DPDK callback to start the device.
  *
@@ -469,7 +522,7 @@ mrvl_dev_start(struct rte_eth_dev *dev)
 {
        struct mrvl_priv *priv = dev->data->dev_private;
        char match[MRVL_MATCH_LEN];
-       int ret = 0, def_init_size;
+       int ret = 0, i, def_init_size;
 
        snprintf(match, sizeof(match), "ppio-%d:%d",
                 priv->pp_id, priv->ppio_id);
@@ -556,6 +609,24 @@ mrvl_dev_start(struct rte_eth_dev *dev)
                goto out;
        }
 
+       /* start tx queues */
+       for (i = 0; i < dev->data->nb_tx_queues; i++) {
+               struct mrvl_txq *txq = dev->data->tx_queues[i];
+
+               dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
+
+               if (!txq->tx_deferred_start)
+                       continue;
+
+               /*
+                * All txqs are started by default. Stop them
+                * so that tx_deferred_start works as expected.
+                */
+               ret = mrvl_tx_queue_stop(dev, i);
+               if (ret)
+                       goto out;
+       }
+
        return 0;
 out:
        RTE_LOG(ERR, PMD, "Failed to start device\n");
@@ -682,12 +753,23 @@ mrvl_dev_stop(struct rte_eth_dev *dev)
        mrvl_dev_set_link_down(dev);
        mrvl_flush_rx_queues(dev);
        mrvl_flush_tx_shadow_queues(dev);
+       if (priv->cls_tbl) {
+               pp2_cls_tbl_deinit(priv->cls_tbl);
+               priv->cls_tbl = NULL;
+       }
        if (priv->qos_tbl) {
                pp2_cls_qos_tbl_deinit(priv->qos_tbl);
                priv->qos_tbl = NULL;
        }
-       pp2_ppio_deinit(priv->ppio);
+       if (priv->ppio)
+               pp2_ppio_deinit(priv->ppio);
        priv->ppio = NULL;
+
+       /* policer must be released after ppio deinitialization */
+       if (priv->policer) {
+               pp2_cls_plcr_deinit(priv->policer);
+               priv->policer = NULL;
+       }
 }
 
 /**
@@ -800,6 +882,9 @@ mrvl_promiscuous_enable(struct rte_eth_dev *dev)
        if (!priv->ppio)
                return;
 
+       if (priv->isolated)
+               return;
+
        ret = pp2_ppio_set_promisc(priv->ppio, 1);
        if (ret)
                RTE_LOG(ERR, PMD, "Failed to enable promiscuous mode\n");
@@ -820,6 +905,9 @@ mrvl_allmulticast_enable(struct rte_eth_dev *dev)
        if (!priv->ppio)
                return;
 
+       if (priv->isolated)
+               return;
+
        ret = pp2_ppio_set_mc_promisc(priv->ppio, 1);
        if (ret)
                RTE_LOG(ERR, PMD, "Failed enable all-multicast mode\n");
@@ -883,6 +971,9 @@ mrvl_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
        if (!priv->ppio)
                return;
 
+       if (priv->isolated)
+               return;
+
        ret = pp2_ppio_remove_mac_addr(priv->ppio,
                                       dev->data->mac_addrs[index].addr_bytes);
        if (ret) {
@@ -915,6 +1006,9 @@ mrvl_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
        char buf[ETHER_ADDR_FMT_SIZE];
        int ret;
 
+       if (priv->isolated)
+               return -ENOTSUP;
+
        if (index == 0)
                /* For setting index 0, mrvl_mac_addr_set() should be used.*/
                return -1;
@@ -952,15 +1046,21 @@ mrvl_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
  *   Pointer to Ethernet device structure.
  * @param mac_addr
  *   MAC address to register.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
  */
-static void
+static int
 mrvl_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
 {
        struct mrvl_priv *priv = dev->data->dev_private;
        int ret;
 
        if (!priv->ppio)
-               return;
+               return 0;
+
+       if (priv->isolated)
+               return -ENOTSUP;
 
        ret = pp2_ppio_set_mac_addr(priv->ppio, mac_addr->addr_bytes);
        if (ret) {
@@ -968,6 +1068,8 @@ mrvl_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
                ether_format_addr(buf, sizeof(buf), mac_addr);
                RTE_LOG(ERR, PMD, "Failed to set mac to %s\n", buf);
        }
+
+       return ret;
 }
 
 /**
@@ -1106,6 +1208,90 @@ mrvl_stats_reset(struct rte_eth_dev *dev)
        pp2_ppio_get_statistics(priv->ppio, NULL, 1);
 }
 
+/**
+ * DPDK callback to get extended statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ * @param stats
+ *   Pointer to xstats table.
+ * @param n
+ *   Number of entries in xstats table.
+ * @return
+ *   Negative value on error, number of read xstats otherwise.
+ */
+static int
+mrvl_xstats_get(struct rte_eth_dev *dev,
+               struct rte_eth_xstat *stats, unsigned int n)
+{
+       struct mrvl_priv *priv = dev->data->dev_private;
+       struct pp2_ppio_statistics ppio_stats;
+       unsigned int i;
+
+       if (!stats)
+               return 0;
+
+       pp2_ppio_get_statistics(priv->ppio, &ppio_stats, 0);
+       for (i = 0; i < n && i < RTE_DIM(mrvl_xstats_tbl); i++) {
+               uint64_t val;
+
+               if (mrvl_xstats_tbl[i].size == sizeof(uint32_t))
+                       val = *(uint32_t *)((uint8_t *)&ppio_stats +
+                                           mrvl_xstats_tbl[i].offset);
+               else if (mrvl_xstats_tbl[i].size == sizeof(uint64_t))
+                       val = *(uint64_t *)((uint8_t *)&ppio_stats +
+                                           mrvl_xstats_tbl[i].offset);
+               else
+                       return -EINVAL;
+
+               stats[i].id = i;
+               stats[i].value = val;
+       }
+
+       return n;
+}
+
+/**
+ * DPDK callback to reset extended statistics.
+ *
+ * @param dev
+ *   Pointer to Ethernet device structure.
+ */
+static void
+mrvl_xstats_reset(struct rte_eth_dev *dev)
+{
+       mrvl_stats_reset(dev);
+}
+
+/**
+ * DPDK callback to get extended statistics names.
+ *
+ * @param dev (unused)
+ *   Pointer to Ethernet device structure.
+ * @param xstats_names
+ *   Pointer to xstats names table.
+ * @param size
+ *   Size of the xstats names table.
+ * @return
+ *   Number of read names.
+ */
+static int
+mrvl_xstats_get_names(struct rte_eth_dev *dev __rte_unused,
+                     struct rte_eth_xstat_name *xstats_names,
+                     unsigned int size)
+{
+       unsigned int i;
+
+       if (!xstats_names)
+               return RTE_DIM(mrvl_xstats_tbl);
+
+       for (i = 0; i < size && i < RTE_DIM(mrvl_xstats_tbl); i++)
+               snprintf(xstats_names[i].name, RTE_ETH_XSTATS_NAME_SIZE, "%s",
+                        mrvl_xstats_tbl[i].name);
+
+       return size;
+}
+
 /**
  * DPDK callback to get information about the device.
  *
@@ -1217,9 +1403,11 @@ static void mrvl_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id,
                              struct rte_eth_txq_info *qinfo)
 {
        struct mrvl_priv *priv = dev->data->dev_private;
+       struct mrvl_txq *txq = dev->data->tx_queues[tx_queue_id];
 
        qinfo->nb_desc =
                priv->ppio_params.outqs_params.outqs_params[tx_queue_id].size;
+       qinfo->conf.tx_deferred_start = txq->tx_deferred_start;
 }
 
 /**
@@ -1243,6 +1431,9 @@ mrvl_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
        if (!priv->ppio)
                return -EPERM;
 
+       if (priv->isolated)
+               return -ENOTSUP;
+
        return on ? pp2_ppio_add_vlan(priv->ppio, vlan_id) :
                    pp2_ppio_remove_vlan(priv->ppio, vlan_id);
 }
@@ -1261,8 +1452,8 @@ mrvl_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
 static int
 mrvl_fill_bpool(struct mrvl_rxq *rxq, int num)
 {
-       struct buff_release_entry entries[MRVL_PP2_TXD_MAX];
-       struct rte_mbuf *mbufs[MRVL_PP2_TXD_MAX];
+       struct buff_release_entry entries[MRVL_PP2_RXD_MAX];
+       struct rte_mbuf *mbufs[MRVL_PP2_RXD_MAX];
        int i, ret;
        unsigned int core_id;
        struct pp2_hif *hif;
@@ -1315,42 +1506,6 @@ out:
        return -1;
 }
 
-/**
- * Check whether requested rx queue offloads match port offloads.
- *
- * @param
- *   dev Pointer to the device.
- * @param
- *   requested Bitmap of the requested offloads.
- *
- * @return
- *   1 if requested offloads are okay, 0 otherwise.
- */
-static int
-mrvl_rx_queue_offloads_okay(struct rte_eth_dev *dev, uint64_t requested)
-{
-       uint64_t mandatory = dev->data->dev_conf.rxmode.offloads;
-       uint64_t supported = MRVL_RX_OFFLOADS;
-       uint64_t unsupported = requested & ~supported;
-       uint64_t missing = mandatory & ~requested;
-
-       if (unsupported) {
-               RTE_LOG(ERR, PMD, "Some Rx offloads are not supported. "
-                       "Requested 0x%" PRIx64 " supported 0x%" PRIx64 ".\n",
-                       requested, supported);
-               return 0;
-       }
-
-       if (missing) {
-               RTE_LOG(ERR, PMD, "Some Rx offloads are missing. "
-                       "Requested 0x%" PRIx64 " missing 0x%" PRIx64 ".\n",
-                       requested, missing);
-               return 0;
-       }
-
-       return 1;
-}
-
 /**
  * DPDK callback to configure the receive queue.
  *
@@ -1381,9 +1536,9 @@ mrvl_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
        uint32_t min_size,
                 max_rx_pkt_len = dev->data->dev_conf.rxmode.max_rx_pkt_len;
        int ret, tc, inq;
+       uint64_t offloads;
 
-       if (!mrvl_rx_queue_offloads_okay(dev, conf->offloads))
-               return -ENOTSUP;
+       offloads = conf->offloads | dev->data->dev_conf.rxmode.offloads;
 
        if (priv->rxq_map[idx].tc == MRVL_UNKNOWN_TC) {
                /*
@@ -1416,8 +1571,7 @@ mrvl_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 
        rxq->priv = priv;
        rxq->mp = mp;
-       rxq->cksum_enabled =
-               dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_IPV4_CKSUM;
+       rxq->cksum_enabled = offloads & DEV_RX_OFFLOAD_IPV4_CKSUM;
        rxq->queue_id = idx;
        rxq->port_id = dev->data->port_id;
        mrvl_port_to_bpool_lookup[rxq->port_id] = priv->bpool;
@@ -1479,42 +1633,6 @@ mrvl_rx_queue_release(void *rxq)
        rte_free(q);
 }
 
-/**
- * Check whether requested tx queue offloads match port offloads.
- *
- * @param
- *   dev Pointer to the device.
- * @param
- *   requested Bitmap of the requested offloads.
- *
- * @return
- *   1 if requested offloads are okay, 0 otherwise.
- */
-static int
-mrvl_tx_queue_offloads_okay(struct rte_eth_dev *dev, uint64_t requested)
-{
-       uint64_t mandatory = dev->data->dev_conf.txmode.offloads;
-       uint64_t supported = MRVL_TX_OFFLOADS;
-       uint64_t unsupported = requested & ~supported;
-       uint64_t missing = mandatory & ~requested;
-
-       if (unsupported) {
-               RTE_LOG(ERR, PMD, "Some Rx offloads are not supported. "
-                       "Requested 0x%" PRIx64 " supported 0x%" PRIx64 ".\n",
-                       requested, supported);
-               return 0;
-       }
-
-       if (missing) {
-               RTE_LOG(ERR, PMD, "Some Rx offloads are missing. "
-                       "Requested 0x%" PRIx64 " missing 0x%" PRIx64 ".\n",
-                       requested, missing);
-               return 0;
-       }
-
-       return 1;
-}
-
 /**
  * DPDK callback to configure the transmit queue.
  *
@@ -1527,7 +1645,7 @@ mrvl_tx_queue_offloads_okay(struct rte_eth_dev *dev, uint64_t requested)
  * @param socket
  *   NUMA socket on which memory must be allocated.
  * @param conf
- *   Thresholds parameters.
+ *   Tx queue configuration parameters.
  *
  * @return
  *   0 on success, negative error value otherwise.
@@ -1540,9 +1658,6 @@ mrvl_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
        struct mrvl_priv *priv = dev->data->dev_private;
        struct mrvl_txq *txq;
 
-       if (!mrvl_tx_queue_offloads_okay(dev, conf->offloads))
-               return -ENOTSUP;
-
        if (dev->data->tx_queues[idx]) {
                rte_free(dev->data->tx_queues[idx]);
                dev->data->tx_queues[idx] = NULL;
@@ -1555,10 +1670,10 @@ mrvl_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
        txq->priv = priv;
        txq->queue_id = idx;
        txq->port_id = dev->data->port_id;
+       txq->tx_deferred_start = conf->tx_deferred_start;
        dev->data->tx_queues[idx] = txq;
 
        priv->ppio_params.outqs_params.outqs_params[idx].size = desc;
-       priv->ppio_params.outqs_params.outqs_params[idx].weight = 1;
 
        return 0;
 }
@@ -1580,6 +1695,82 @@ mrvl_tx_queue_release(void *txq)
        rte_free(q);
 }
 
+/**
+ * DPDK callback to get flow control configuration.
+ *
+ * @param dev
+ *  Pointer to Ethernet device structure.
+ * @param fc_conf
+ *  Pointer to the flow control configuration.
+ *
+ * @return
+ *  0 on success, negative error value otherwise.
+ */
+static int
+mrvl_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
+{
+       struct mrvl_priv *priv = dev->data->dev_private;
+       int ret, en;
+
+       if (!priv)
+               return -EPERM;
+
+       ret = pp2_ppio_get_rx_pause(priv->ppio, &en);
+       if (ret) {
+               RTE_LOG(ERR, PMD, "Failed to read rx pause state\n");
+               return ret;
+       }
+
+       fc_conf->mode = en ? RTE_FC_RX_PAUSE : RTE_FC_NONE;
+
+       return 0;
+}
+
+/**
+ * DPDK callback to set flow control configuration.
+ *
+ * @param dev
+ *  Pointer to Ethernet device structure.
+ * @param fc_conf
+ *  Pointer to the flow control configuration.
+ *
+ * @return
+ *  0 on success, negative error value otherwise.
+ */
+static int
+mrvl_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
+{
+       struct mrvl_priv *priv = dev->data->dev_private;
+
+       if (!priv)
+               return -EPERM;
+
+       if (fc_conf->high_water ||
+           fc_conf->low_water ||
+           fc_conf->pause_time ||
+           fc_conf->mac_ctrl_frame_fwd ||
+           fc_conf->autoneg) {
+               RTE_LOG(ERR, PMD, "Flowctrl parameter is not supported\n");
+
+               return -EINVAL;
+       }
+
+       if (fc_conf->mode == RTE_FC_NONE ||
+           fc_conf->mode == RTE_FC_RX_PAUSE) {
+               int ret, en;
+
+               en = fc_conf->mode == RTE_FC_NONE ? 0 : 1;
+               ret = pp2_ppio_set_rx_pause(priv->ppio, en);
+               if (ret)
+                       RTE_LOG(ERR, PMD,
+                               "Failed to change flowctrl on RX side\n");
+
+               return ret;
+       }
+
+       return 0;
+}
+
 /**
  * Update RSS hash configuration
  *
@@ -1597,6 +1788,9 @@ mrvl_rss_hash_update(struct rte_eth_dev *dev,
 {
        struct mrvl_priv *priv = dev->data->dev_private;
 
+       if (priv->isolated)
+               return -ENOTSUP;
+
        return mrvl_configure_rss(priv, rss_conf);
 }
 
@@ -1633,6 +1827,39 @@ mrvl_rss_hash_conf_get(struct rte_eth_dev *dev,
        return 0;
 }
 
+/**
+ * DPDK callback to get rte_flow callbacks.
+ *
+ * @param dev
+ *   Pointer to the device structure.
+ * @param filer_type
+ *   Flow filter type.
+ * @param filter_op
+ *   Flow filter operation.
+ * @param arg
+ *   Pointer to pass the flow ops.
+ *
+ * @return
+ *   0 on success, negative error value otherwise.
+ */
+static int
+mrvl_eth_filter_ctrl(struct rte_eth_dev *dev __rte_unused,
+                    enum rte_filter_type filter_type,
+                    enum rte_filter_op filter_op, void *arg)
+{
+       switch (filter_type) {
+       case RTE_ETH_FILTER_GENERIC:
+               if (filter_op != RTE_ETH_FILTER_GET)
+                       return -EINVAL;
+               *(const void **)arg = &mrvl_flow_ops;
+               return 0;
+       default:
+               RTE_LOG(WARNING, PMD, "Filter type (%d) not supported",
+                               filter_type);
+               return -EINVAL;
+       }
+}
+
 static const struct eth_dev_ops mrvl_ops = {
        .dev_configure = mrvl_dev_configure,
        .dev_start = mrvl_dev_start,
@@ -1651,17 +1878,25 @@ static const struct eth_dev_ops mrvl_ops = {
        .mtu_set = mrvl_mtu_set,
        .stats_get = mrvl_stats_get,
        .stats_reset = mrvl_stats_reset,
+       .xstats_get = mrvl_xstats_get,
+       .xstats_reset = mrvl_xstats_reset,
+       .xstats_get_names = mrvl_xstats_get_names,
        .dev_infos_get = mrvl_dev_infos_get,
        .dev_supported_ptypes_get = mrvl_dev_supported_ptypes_get,
        .rxq_info_get = mrvl_rxq_info_get,
        .txq_info_get = mrvl_txq_info_get,
        .vlan_filter_set = mrvl_vlan_filter_set,
+       .tx_queue_start = mrvl_tx_queue_start,
+       .tx_queue_stop = mrvl_tx_queue_stop,
        .rx_queue_setup = mrvl_rx_queue_setup,
        .rx_queue_release = mrvl_rx_queue_release,
        .tx_queue_setup = mrvl_tx_queue_setup,
        .tx_queue_release = mrvl_tx_queue_release,
+       .flow_ctrl_get = mrvl_flow_ctrl_get,
+       .flow_ctrl_set = mrvl_flow_ctrl_set,
        .rss_hash_update = mrvl_rss_hash_update,
        .rss_hash_conf_get = mrvl_rss_hash_conf_get,
+       .filter_ctrl = mrvl_eth_filter_ctrl,
 };
 
 /**
@@ -2280,6 +2515,7 @@ mrvl_eth_dev_create(struct rte_vdev_device *vdev, const char *name)
        eth_dev->device = &vdev->device;
        eth_dev->dev_ops = &mrvl_ops;
 
+       rte_eth_dev_probing_finish(eth_dev);
        return 0;
 out_free_mac:
        rte_free(eth_dev->data->mac_addrs);
@@ -2484,7 +2720,7 @@ rte_pmd_mrvl_remove(struct rte_vdev_device *vdev)
 
        RTE_LOG(INFO, PMD, "Removing %s\n", name);
 
-       for (i = 0; i < rte_eth_dev_count(); i++) {
+       RTE_ETH_FOREACH_DEV(i) { /* FIXME: removing all devices! */
                char ifname[RTE_ETH_NAME_MAX_LEN];
 
                rte_eth_dev_get_name_by_port(i, ifname);
@@ -2507,5 +2743,5 @@ static struct rte_vdev_driver pmd_mrvl_drv = {
        .remove = rte_pmd_mrvl_remove,
 };
 
-RTE_PMD_REGISTER_VDEV(net_mrvl, pmd_mrvl_drv);
-RTE_PMD_REGISTER_ALIAS(net_mrvl, eth_mrvl);
+RTE_PMD_REGISTER_VDEV(net_mvpp2, pmd_mrvl_drv);
+RTE_PMD_REGISTER_ALIAS(net_mvpp2, eth_mvpp2);