net/mrvl: check if ppio is initialized
[dpdk.git] / drivers / net / mrvl / mrvl_ethdev.c
index 4beaa1d..40f2ead 100644 (file)
@@ -1,7 +1,9 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2017 Semihalf. All rights reserved.
+ *   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
@@ -34,7 +36,7 @@
 #include <rte_kvargs.h>
 #include <rte_log.h>
 #include <rte_malloc.h>
-#include <rte_vdev.h>
+#include <rte_bus_vdev.h>
 
 /* Unluckily, container_of is defined by both DPDK and MUSDK,
  * we'll declare only one version.
 #undef container_of
 #endif
 
-#include <drivers/mv_pp2.h>
-#include <drivers/mv_pp2_bpool.h>
-#include <drivers/mv_pp2_hif.h>
-
 #include <fcntl.h>
 #include <linux/ethtool.h>
 #include <linux/sockios.h>
@@ -93,6 +91,9 @@
 #define MRVL_COOKIE_HIGH_ADDR_SHIFT    (sizeof(pp2_cookie_t) * 8)
 #define MRVL_COOKIE_HIGH_ADDR_MASK     (~0ULL << MRVL_COOKIE_HIGH_ADDR_SHIFT)
 
+/* Memory size (in bytes) for MUSDK dma buffers */
+#define MRVL_MUSDK_DMA_MEMSIZE 41943040
+
 static const char * const valid_args[] = {
        MRVL_IFACE_NAME_ARG,
        MRVL_CFG_ARG,
@@ -323,6 +324,9 @@ mrvl_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
        if (mtu < ETHER_MIN_MTU || mru > MRVL_PKT_SIZE_MAX)
                return -EINVAL;
 
+       if (!priv->ppio)
+               return -EPERM;
+
        ret = pp2_ppio_set_mru(priv->ppio, mru);
        if (ret)
                return ret;
@@ -345,6 +349,9 @@ mrvl_dev_set_link_up(struct rte_eth_dev *dev)
        struct mrvl_priv *priv = dev->data->dev_private;
        int ret;
 
+       if (!priv->ppio)
+               return -EPERM;
+
        ret = pp2_ppio_enable(priv->ppio);
        if (ret)
                return ret;
@@ -360,8 +367,6 @@ mrvl_dev_set_link_up(struct rte_eth_dev *dev)
        if (ret)
                pp2_ppio_disable(priv->ppio);
 
-       dev->data->dev_link.link_status = ETH_LINK_UP;
-
        return ret;
 }
 
@@ -378,15 +383,11 @@ static int
 mrvl_dev_set_link_down(struct rte_eth_dev *dev)
 {
        struct mrvl_priv *priv = dev->data->dev_private;
-       int ret;
 
-       ret = pp2_ppio_disable(priv->ppio);
-       if (ret)
-               return ret;
+       if (!priv->ppio)
+               return -EPERM;
 
-       dev->data->dev_link.link_status = ETH_LINK_DOWN;
-
-       return ret;
+       return pp2_ppio_disable(priv->ppio);
 }
 
 /**
@@ -627,9 +628,13 @@ mrvl_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
         * TODO
         * once MUSDK provides necessary API use it here
         */
+       struct mrvl_priv *priv = dev->data->dev_private;
        struct ethtool_cmd edata;
        struct ifreq req;
-       int ret, fd;
+       int ret, fd, link_up;
+
+       if (!priv->ppio)
+               return -EPERM;
 
        edata.cmd = ETHTOOL_GSET;
 
@@ -669,6 +674,8 @@ mrvl_link_update(struct rte_eth_dev *dev, int wait_to_complete __rte_unused)
                                                         ETH_LINK_HALF_DUPLEX;
        dev->data->dev_link.link_autoneg = edata.autoneg ? ETH_LINK_AUTONEG :
                                                           ETH_LINK_FIXED;
+       pp2_ppio_get_link_state(priv->ppio, &link_up);
+       dev->data->dev_link.link_status = link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
 
        return 0;
 }
@@ -685,7 +692,10 @@ mrvl_promiscuous_enable(struct rte_eth_dev *dev)
        struct mrvl_priv *priv = dev->data->dev_private;
        int ret;
 
-       ret = pp2_ppio_set_uc_promisc(priv->ppio, 1);
+       if (!priv->ppio)
+               return;
+
+       ret = pp2_ppio_set_promisc(priv->ppio, 1);
        if (ret)
                RTE_LOG(ERR, PMD, "Failed to enable promiscuous mode\n");
 }
@@ -702,6 +712,9 @@ mrvl_allmulticast_enable(struct rte_eth_dev *dev)
        struct mrvl_priv *priv = dev->data->dev_private;
        int ret;
 
+       if (!priv->ppio)
+               return;
+
        ret = pp2_ppio_set_mc_promisc(priv->ppio, 1);
        if (ret)
                RTE_LOG(ERR, PMD, "Failed enable all-multicast mode\n");
@@ -719,7 +732,10 @@ mrvl_promiscuous_disable(struct rte_eth_dev *dev)
        struct mrvl_priv *priv = dev->data->dev_private;
        int ret;
 
-       ret = pp2_ppio_set_uc_promisc(priv->ppio, 0);
+       if (!priv->ppio)
+               return;
+
+       ret = pp2_ppio_set_promisc(priv->ppio, 0);
        if (ret)
                RTE_LOG(ERR, PMD, "Failed to disable promiscuous mode\n");
 }
@@ -736,6 +752,9 @@ mrvl_allmulticast_disable(struct rte_eth_dev *dev)
        struct mrvl_priv *priv = dev->data->dev_private;
        int ret;
 
+       if (!priv->ppio)
+               return;
+
        ret = pp2_ppio_set_mc_promisc(priv->ppio, 0);
        if (ret)
                RTE_LOG(ERR, PMD, "Failed to disable all-multicast mode\n");
@@ -756,6 +775,9 @@ mrvl_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
        char buf[ETHER_ADDR_FMT_SIZE];
        int ret;
 
+       if (!priv->ppio)
+               return;
+
        ret = pp2_ppio_remove_mac_addr(priv->ppio,
                                       dev->data->mac_addrs[index].addr_bytes);
        if (ret) {
@@ -792,6 +814,9 @@ mrvl_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr,
                /* For setting index 0, mrvl_mac_addr_set() should be used.*/
                return -1;
 
+       if (!priv->ppio)
+               return -EPERM;
+
        /*
         * Maximum number of uc addresses can be tuned via kernel module mvpp2x
         * parameter uc_filter_max. Maximum number of mc addresses is then
@@ -827,15 +852,17 @@ static void
 mrvl_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
 {
        struct mrvl_priv *priv = dev->data->dev_private;
+       int ret;
 
-       pp2_ppio_set_mac_addr(priv->ppio, mac_addr->addr_bytes);
-       /*
-        * TODO
-        * Port stops sending packets if pp2_ppio_set_mac_addr()
-        * was called after pp2_ppio_enable(). As a quick fix issue
-        * enable port once again.
-        */
-       pp2_ppio_enable(priv->ppio);
+       if (!priv->ppio)
+               return;
+
+       ret = pp2_ppio_set_mac_addr(priv->ppio, mac_addr->addr_bytes);
+       if (ret) {
+               char buf[ETHER_ADDR_FMT_SIZE];
+               ether_format_addr(buf, sizeof(buf), mac_addr);
+               RTE_LOG(ERR, PMD, "Failed to set mac to %s\n", buf);
+       }
 }
 
 /**
@@ -857,6 +884,9 @@ mrvl_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
        uint64_t drop_mac = 0;
        unsigned int i, idx, ret;
 
+       if (!priv->ppio)
+               return -EPERM;
+
        for (i = 0; i < dev->data->nb_rx_queues; i++) {
                struct mrvl_rxq *rxq = dev->data->rx_queues[i];
                struct pp2_ppio_inq_statistics rx_stats;
@@ -949,6 +979,9 @@ mrvl_stats_reset(struct rte_eth_dev *dev)
        struct mrvl_priv *priv = dev->data->dev_private;
        int i;
 
+       if (!priv->ppio)
+               return;
+
        for (i = 0; i < dev->data->nb_rx_queues; i++) {
                struct mrvl_rxq *rxq = dev->data->rx_queues[i];
 
@@ -1105,6 +1138,9 @@ mrvl_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
 {
        struct mrvl_priv *priv = dev->data->dev_private;
 
+       if (!priv->ppio)
+               return -EPERM;
+
        return on ? pp2_ppio_add_vlan(priv->ppio, vlan_id) :
                    pp2_ppio_remove_vlan(priv->ppio, vlan_id);
 }
@@ -1148,7 +1184,7 @@ mrvl_fill_bpool(struct mrvl_rxq *rxq, int num)
                }
 
                entries[i].buff.addr =
-                       rte_mbuf_data_dma_addr_default(mbufs[i]);
+                       rte_mbuf_data_iova_default(mbufs[i]);
                entries[i].buff.cookie = (pp2_cookie_t)(uint64_t)mbufs[i];
                entries[i].bpool = bpool;
        }
@@ -1593,7 +1629,7 @@ mrvl_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
                status = pp2_ppio_inq_desc_get_l2_pkt_error(&descs[i]);
                if (unlikely(status != PP2_DESC_ERR_OK)) {
                        struct pp2_buff_inf binf = {
-                               .addr = rte_mbuf_data_dma_addr_default(mbuf),
+                               .addr = rte_mbuf_data_iova_default(mbuf),
                                .cookie = (pp2_cookie_t)(uint64_t)mbuf,
                        };
 
@@ -1849,7 +1885,7 @@ mrvl_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 
                sq->ent[sq->head].buff.cookie = (pp2_cookie_t)(uint64_t)mbuf;
                sq->ent[sq->head].buff.addr =
-                       rte_mbuf_data_dma_addr_default(mbuf);
+                       rte_mbuf_data_iova_default(mbuf);
                sq->ent[sq->head].bpool =
                        (unlikely(mbuf->port == 0xff || mbuf->refcnt > 1)) ?
                         NULL : mrvl_port_to_bpool_lookup[mbuf->port];
@@ -1858,7 +1894,7 @@ mrvl_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 
                pp2_ppio_outq_desc_reset(&descs[i]);
                pp2_ppio_outq_desc_set_phys_addr(&descs[i],
-                                                rte_pktmbuf_mtophys(mbuf));
+                                                rte_pktmbuf_iova(mbuf));
                pp2_ppio_outq_desc_set_pkt_offset(&descs[i], 0);
                pp2_ppio_outq_desc_set_pkt_len(&descs[i],
                                               rte_pktmbuf_pkt_len(mbuf));
@@ -2193,9 +2229,14 @@ rte_pmd_mrvl_probe(struct rte_vdev_device *vdev)
         * ret == -EEXIST is correct, it means DMA
         * has been already initialized (by another PMD).
         */
-       ret = mv_sys_dma_mem_init(RTE_MRVL_MUSDK_DMA_MEMSIZE);
-       if (ret < 0 && ret != -EEXIST)
-               goto out_free_kvlist;
+       ret = mv_sys_dma_mem_init(MRVL_MUSDK_DMA_MEMSIZE);
+       if (ret < 0) {
+               if (ret != -EEXIST)
+                       goto out_free_kvlist;
+               else
+                       RTE_LOG(INFO, PMD,
+                               "DMA memory has been already initialized by a different driver.\n");
+       }
 
        ret = mrvl_init_pp2();
        if (ret) {