net/octeontx: add basic stats support
[dpdk.git] / drivers / net / octeontx / octeontx_ethdev.c
index 7388172..8eb6bdd 100644 (file)
@@ -53,6 +53,17 @@ struct octeontx_vdev_init_params {
        uint8_t nr_port;
 };
 
+enum octeontx_link_speed {
+       OCTEONTX_LINK_SPEED_SGMII,
+       OCTEONTX_LINK_SPEED_XAUI,
+       OCTEONTX_LINK_SPEED_RXAUI,
+       OCTEONTX_LINK_SPEED_10G_R,
+       OCTEONTX_LINK_SPEED_40G_R,
+       OCTEONTX_LINK_SPEED_RESERVE1,
+       OCTEONTX_LINK_SPEED_QSGMII,
+       OCTEONTX_LINK_SPEED_RESERVE2
+};
+
 /* Parse integer from integer argument */
 static int
 parse_integer_arg(const char *key __rte_unused,
@@ -149,6 +160,60 @@ octeontx_port_close(struct octeontx_nic *nic)
        octeontx_log_dbg("port closed %d", nic->port_id);
 }
 
+static void
+octeontx_port_promisc_set(struct octeontx_nic *nic, int en)
+{
+       struct rte_eth_dev *dev;
+       int res;
+
+       res = 0;
+       PMD_INIT_FUNC_TRACE();
+       dev = nic->dev;
+
+       res = octeontx_bgx_port_promisc_set(nic->port_id, en);
+       if (res < 0)
+               octeontx_log_err("failed to set promiscuous mode %d",
+                               nic->port_id);
+
+       /* Set proper flag for the mode */
+       dev->data->promiscuous = (en != 0) ? 1 : 0;
+
+       octeontx_log_dbg("port %d : promiscuous mode %s",
+                       nic->port_id, en ? "set" : "unset");
+}
+
+static void
+octeontx_port_stats(struct octeontx_nic *nic, struct rte_eth_stats *stats)
+{
+       octeontx_mbox_bgx_port_stats_t bgx_stats;
+       int res;
+
+       PMD_INIT_FUNC_TRACE();
+
+       res = octeontx_bgx_port_stats(nic->port_id, &bgx_stats);
+       if (res < 0)
+               octeontx_log_err("failed to get port stats %d", nic->port_id);
+
+       stats->ipackets = bgx_stats.rx_packets;
+       stats->ibytes = bgx_stats.rx_bytes;
+       stats->imissed = bgx_stats.rx_dropped;
+       stats->ierrors = bgx_stats.rx_errors;
+       stats->opackets = bgx_stats.tx_packets;
+       stats->obytes = bgx_stats.tx_bytes;
+       stats->oerrors = bgx_stats.tx_errors;
+
+       octeontx_log_dbg("port%d stats inpkts=%" PRIx64 " outpkts=%" PRIx64 "",
+                       nic->port_id, stats->ipackets, stats->opackets);
+}
+
+static void
+octeontx_port_stats_clr(struct octeontx_nic *nic)
+{
+       PMD_INIT_FUNC_TRACE();
+
+       octeontx_bgx_port_stats_clr(nic->port_id);
+}
+
 static inline void
 devconf_set_default_sane_values(struct rte_event_dev_config *dev_conf,
                                struct rte_event_dev_info *info)
@@ -262,9 +327,175 @@ octeontx_dev_configure(struct rte_eth_dev *dev)
        return 0;
 }
 
+static void
+octeontx_dev_promisc_enable(struct rte_eth_dev *dev)
+{
+       struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+
+       PMD_INIT_FUNC_TRACE();
+       octeontx_port_promisc_set(nic, 1);
+}
+
+static void
+octeontx_dev_promisc_disable(struct rte_eth_dev *dev)
+{
+       struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+
+       PMD_INIT_FUNC_TRACE();
+       octeontx_port_promisc_set(nic, 0);
+}
+
+static inline int
+octeontx_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 int
+octeontx_port_link_status(struct octeontx_nic *nic)
+{
+       int res;
+
+       PMD_INIT_FUNC_TRACE();
+       res = octeontx_bgx_port_link_status(nic->port_id);
+       if (res < 0) {
+               octeontx_log_err("failed to get port %d link status",
+                               nic->port_id);
+               return res;
+       }
+
+       nic->link_up = (uint8_t)res;
+       octeontx_log_dbg("port %d link status %d", nic->port_id, nic->link_up);
+
+       return res;
+}
+
+/*
+ * Return 0 means link status changed, -1 means not changed
+ */
+static int
+octeontx_dev_link_update(struct rte_eth_dev *dev,
+                        int wait_to_complete __rte_unused)
+{
+       struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+       struct rte_eth_link link;
+       int res;
+
+       res = 0;
+       PMD_INIT_FUNC_TRACE();
+
+       res = octeontx_port_link_status(nic);
+       if (res < 0) {
+               octeontx_log_err("failed to request link status %d", res);
+               return res;
+       }
+
+       link.link_status = nic->link_up;
+
+       switch (nic->speed) {
+       case OCTEONTX_LINK_SPEED_SGMII:
+               link.link_speed = ETH_SPEED_NUM_1G;
+               break;
+
+       case OCTEONTX_LINK_SPEED_XAUI:
+               link.link_speed = ETH_SPEED_NUM_10G;
+               break;
+
+       case OCTEONTX_LINK_SPEED_RXAUI:
+       case OCTEONTX_LINK_SPEED_10G_R:
+               link.link_speed = ETH_SPEED_NUM_10G;
+               break;
+       case OCTEONTX_LINK_SPEED_QSGMII:
+               link.link_speed = ETH_SPEED_NUM_5G;
+               break;
+       case OCTEONTX_LINK_SPEED_40G_R:
+               link.link_speed = ETH_SPEED_NUM_40G;
+               break;
+
+       case OCTEONTX_LINK_SPEED_RESERVE1:
+       case OCTEONTX_LINK_SPEED_RESERVE2:
+       default:
+               octeontx_log_err("incorrect link speed %d", nic->speed);
+               break;
+       }
+
+       link.link_duplex = ETH_LINK_AUTONEG;
+       link.link_autoneg = ETH_LINK_SPEED_AUTONEG;
+
+       return octeontx_atomic_write_link_status(dev, &link);
+}
+
+static void
+octeontx_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+       struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+
+       PMD_INIT_FUNC_TRACE();
+       octeontx_port_stats(nic, stats);
+}
+
+static void
+octeontx_dev_stats_reset(struct rte_eth_dev *dev)
+{
+       struct octeontx_nic *nic = octeontx_pmd_priv(dev);
+
+       PMD_INIT_FUNC_TRACE();
+       octeontx_port_stats_clr(nic);
+}
+
+static void
+octeontx_dev_info(struct rte_eth_dev *dev,
+               struct rte_eth_dev_info *dev_info)
+{
+       RTE_SET_USED(dev);
+
+       /* Autonegotiation may be disabled */
+       dev_info->speed_capa = ETH_LINK_SPEED_FIXED;
+       dev_info->speed_capa |= ETH_LINK_SPEED_10M | ETH_LINK_SPEED_100M |
+                       ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G |
+                       ETH_LINK_SPEED_40G;
+
+       dev_info->driver_name = RTE_STR(rte_octeontx_pmd);
+       dev_info->max_mac_addrs = 1;
+       dev_info->max_rx_pktlen = PKI_MAX_PKTLEN;
+       dev_info->max_rx_queues = 1;
+       dev_info->max_tx_queues = PKO_MAX_NUM_DQ;
+       dev_info->min_rx_bufsize = 0;
+       dev_info->pci_dev = NULL;
+
+       dev_info->default_rxconf = (struct rte_eth_rxconf) {
+               .rx_free_thresh = 0,
+               .rx_drop_en = 0,
+       };
+
+       dev_info->default_txconf = (struct rte_eth_txconf) {
+               .tx_free_thresh = 0,
+               .txq_flags =
+                       ETH_TXQ_FLAGS_NOMULTSEGS |
+                       ETH_TXQ_FLAGS_NOOFFLOADS |
+                       ETH_TXQ_FLAGS_NOXSUMS,
+       };
+
+       dev_info->tx_offload_capa = DEV_TX_OFFLOAD_MT_LOCKFREE;
+}
+
 /* Initialize and register driver with DPDK Application */
 static const struct eth_dev_ops octeontx_dev_ops = {
        .dev_configure           = octeontx_dev_configure,
+       .dev_infos_get           = octeontx_dev_info,
+       .promiscuous_enable      = octeontx_dev_promisc_enable,
+       .promiscuous_disable     = octeontx_dev_promisc_disable,
+       .link_update             = octeontx_dev_link_update,
+       .stats_get               = octeontx_dev_stats_get,
+       .stats_reset             = octeontx_dev_stats_reset,
 };
 
 /* Create Ethdev interface per BGX LMAC ports */