net/dpaa2: enable DMA mapping during device scanning
[dpdk.git] / drivers / net / dpaa2 / dpaa2_ethdev.c
index e037bdb..999d0ad 100644 (file)
 
 static struct rte_dpaa2_driver rte_dpaa2_pmd;
 
+/**
+ * Atomically reads the link status information from global
+ * structure rte_eth_dev.
+ *
+ * @param dev
+ *   - Pointer to the structure rte_eth_dev to read from.
+ *   - Pointer to the buffer to be saved with the link status.
+ *
+ * @return
+ *   - On success, zero.
+ *   - On failure, negative value.
+ */
+static inline int
+dpaa2_dev_atomic_read_link_status(struct rte_eth_dev *dev,
+                                 struct rte_eth_link *link)
+{
+       struct rte_eth_link *dst = link;
+       struct rte_eth_link *src = &dev->data->dev_link;
+
+       if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
+                               *(uint64_t *)src) == 0)
+               return -1;
+
+       return 0;
+}
+
+/**
+ * Atomically writes the link status information into global
+ * structure rte_eth_dev.
+ *
+ * @param dev
+ *   - Pointer to the structure rte_eth_dev to read from.
+ *   - Pointer to the buffer to be saved with the link status.
+ *
+ * @return
+ *   - On success, zero.
+ *   - On failure, negative value.
+ */
+static inline int
+dpaa2_dev_atomic_write_link_status(struct rte_eth_dev *dev,
+                                  struct rte_eth_link *link)
+{
+       struct rte_eth_link *dst = &dev->data->dev_link;
+       struct rte_eth_link *src = link;
+
+       if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
+                               *(uint64_t *)src) == 0)
+               return -1;
+
+       return 0;
+}
+
 static void
 dpaa2_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
@@ -225,6 +277,17 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev,
        options = options | DPNI_QUEUE_OPT_USER_CTX;
        cfg.user_context = (uint64_t)(dpaa2_q);
 
+       /*if ls2088 or rev2 device, enable the stashing */
+       if ((qbman_get_version() & 0xFFFF0000) > QMAN_REV_4000) {
+               options |= DPNI_QUEUE_OPT_FLC;
+               cfg.flc.stash_control = true;
+               cfg.flc.value &= 0xFFFFFFFFFFFFFFC0;
+               /* 00 00 00 - last 6 bit represent annotation, context stashing,
+                * data stashing setting 01 01 00 (0x14) to enable
+                * 1 line annotation, 1 line context
+                */
+               cfg.flc.value |= 0x14;
+       }
        ret = dpni_set_queue(dpni, CMD_PRI_LOW, priv->token, DPNI_QUEUE_RX,
                             dpaa2_q->tc_index, flow_id, options, &cfg);
        if (ret) {
@@ -310,6 +373,28 @@ dpaa2_dev_tx_queue_release(void *q __rte_unused)
        PMD_INIT_FUNC_TRACE();
 }
 
+static const uint32_t *
+dpaa2_supported_ptypes_get(struct rte_eth_dev *dev)
+{
+       static const uint32_t ptypes[] = {
+               /*todo -= add more types */
+               RTE_PTYPE_L2_ETHER,
+               RTE_PTYPE_L3_IPV4,
+               RTE_PTYPE_L3_IPV4_EXT,
+               RTE_PTYPE_L3_IPV6,
+               RTE_PTYPE_L3_IPV6_EXT,
+               RTE_PTYPE_L4_TCP,
+               RTE_PTYPE_L4_UDP,
+               RTE_PTYPE_L4_SCTP,
+               RTE_PTYPE_L4_ICMP,
+               RTE_PTYPE_UNKNOWN
+       };
+
+       if (dev->rx_pkt_burst == dpaa2_dev_rx)
+               return ptypes;
+       return NULL;
+}
+
 static int
 dpaa2_dev_start(struct rte_eth_dev *dev)
 {
@@ -408,6 +493,7 @@ dpaa2_dev_stop(struct rte_eth_dev *dev)
        struct dpaa2_dev_priv *priv = dev->data->dev_private;
        struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
        int ret;
+       struct rte_eth_link link;
 
        PMD_INIT_FUNC_TRACE();
 
@@ -417,6 +503,10 @@ dpaa2_dev_stop(struct rte_eth_dev *dev)
                             ret, priv->hw_id);
                return;
        }
+
+       /* clear the recorded link status */
+       memset(&link, 0, sizeof(link));
+       dpaa2_dev_atomic_write_link_status(dev, &link);
 }
 
 static void
@@ -509,6 +599,139 @@ dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
        return 0;
 }
 
+static
+void dpaa2_dev_stats_get(struct rte_eth_dev *dev,
+                        struct rte_eth_stats *stats)
+{
+       struct dpaa2_dev_priv *priv = dev->data->dev_private;
+       struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+       int32_t  retcode;
+       uint8_t page0 = 0, page1 = 1, page2 = 2;
+       union dpni_statistics value;
+
+       memset(&value, 0, sizeof(union dpni_statistics));
+
+       PMD_INIT_FUNC_TRACE();
+
+       if (!dpni) {
+               RTE_LOG(ERR, PMD, "dpni is NULL");
+               return;
+       }
+
+       if (!stats) {
+               RTE_LOG(ERR, PMD, "stats is NULL");
+               return;
+       }
+
+       /*Get Counters from page_0*/
+       retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token,
+                                     page0, &value);
+       if (retcode)
+               goto err;
+
+       stats->ipackets = value.page_0.ingress_all_frames;
+       stats->ibytes = value.page_0.ingress_all_bytes;
+
+       /*Get Counters from page_1*/
+       retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token,
+                                     page1, &value);
+       if (retcode)
+               goto err;
+
+       stats->opackets = value.page_1.egress_all_frames;
+       stats->obytes = value.page_1.egress_all_bytes;
+
+       /*Get Counters from page_2*/
+       retcode = dpni_get_statistics(dpni, CMD_PRI_LOW, priv->token,
+                                     page2, &value);
+       if (retcode)
+               goto err;
+
+       stats->ierrors = value.page_2.ingress_discarded_frames;
+       stats->oerrors = value.page_2.egress_discarded_frames;
+       stats->imissed = value.page_2.ingress_nobuffer_discards;
+
+       return;
+
+err:
+       RTE_LOG(ERR, PMD, "Operation not completed:Error Code = %d\n", retcode);
+       return;
+};
+
+static
+void dpaa2_dev_stats_reset(struct rte_eth_dev *dev)
+{
+       struct dpaa2_dev_priv *priv = dev->data->dev_private;
+       struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+       int32_t  retcode;
+
+       PMD_INIT_FUNC_TRACE();
+
+       if (dpni == NULL) {
+               RTE_LOG(ERR, PMD, "dpni is NULL");
+               return;
+       }
+
+       retcode =  dpni_reset_statistics(dpni, CMD_PRI_LOW, priv->token);
+       if (retcode)
+               goto error;
+
+       return;
+
+error:
+       RTE_LOG(ERR, PMD, "Operation not completed:Error Code = %d\n", retcode);
+       return;
+};
+
+/* return 0 means link status changed, -1 means not changed */
+static int
+dpaa2_dev_link_update(struct rte_eth_dev *dev,
+                       int wait_to_complete __rte_unused)
+{
+       int ret;
+       struct dpaa2_dev_priv *priv = dev->data->dev_private;
+       struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
+       struct rte_eth_link link, old;
+       struct dpni_link_state state = {0};
+
+       PMD_INIT_FUNC_TRACE();
+
+       if (dpni == NULL) {
+               RTE_LOG(ERR, PMD, "error : dpni is NULL");
+               return 0;
+       }
+       memset(&old, 0, sizeof(old));
+       dpaa2_dev_atomic_read_link_status(dev, &old);
+
+       ret = dpni_get_link_state(dpni, CMD_PRI_LOW, priv->token, &state);
+       if (ret < 0) {
+               RTE_LOG(ERR, PMD, "error: dpni_get_link_state %d", ret);
+               return -1;
+       }
+
+       if ((old.link_status == state.up) && (old.link_speed == state.rate)) {
+               RTE_LOG(DEBUG, PMD, "No change in status\n");
+               return -1;
+       }
+
+       memset(&link, 0, sizeof(struct rte_eth_link));
+       link.link_status = state.up;
+       link.link_speed = state.rate;
+
+       if (state.options & DPNI_LINK_OPT_HALF_DUPLEX)
+               link.link_duplex = ETH_LINK_HALF_DUPLEX;
+       else
+               link.link_duplex = ETH_LINK_FULL_DUPLEX;
+
+       dpaa2_dev_atomic_write_link_status(dev, &link);
+
+       if (link.link_status)
+               PMD_DRV_LOG(INFO, "Port %d Link is Up\n", dev->data->port_id);
+       else
+               PMD_DRV_LOG(INFO, "Port %d Link is Down\n", dev->data->port_id);
+       return 0;
+}
+
 static struct eth_dev_ops dpaa2_ethdev_ops = {
        .dev_configure    = dpaa2_eth_dev_configure,
        .dev_start            = dpaa2_dev_start,
@@ -516,7 +739,11 @@ static struct eth_dev_ops dpaa2_ethdev_ops = {
        .dev_close            = dpaa2_dev_close,
        .promiscuous_enable   = dpaa2_dev_promiscuous_enable,
        .promiscuous_disable  = dpaa2_dev_promiscuous_disable,
+       .link_update       = dpaa2_dev_link_update,
+       .stats_get             = dpaa2_dev_stats_get,
+       .stats_reset       = dpaa2_dev_stats_reset,
        .dev_infos_get     = dpaa2_dev_info_get,
+       .dev_supported_ptypes_get = dpaa2_supported_ptypes_get,
        .mtu_set           = dpaa2_dev_mtu_set,
        .rx_queue_setup    = dpaa2_dev_rx_queue_setup,
        .rx_queue_release  = dpaa2_dev_rx_queue_release,
@@ -679,6 +906,10 @@ dpaa2_dev_init(struct rte_eth_dev *eth_dev)
        eth_dev->dev_ops = &dpaa2_ethdev_ops;
        eth_dev->data->drv_name = rte_dpaa2_pmd.driver.name;
 
+       eth_dev->rx_pkt_burst = dpaa2_dev_rx;
+       eth_dev->tx_pkt_burst = dpaa2_dev_tx;
+       rte_fslmc_vfio_dmamap();
+
        return 0;
 }
 
@@ -732,6 +963,8 @@ dpaa2_dev_uninit(struct rte_eth_dev *eth_dev)
        free(dpni);
 
        eth_dev->dev_ops = NULL;
+       eth_dev->rx_pkt_burst = NULL;
+       eth_dev->tx_pkt_burst = NULL;
 
        return 0;
 }