From: Rakesh Kudurumalla <[email protected]>

Add ethdev FEC operations for cnxk NIX driver:
- fec_get_capability: Report supported FEC modes per speed.
  If firmware provides supported FEC info, return actual
  capabilities for current link speed. Otherwise, fall back
  to a default capability table for common speeds.
- fec_get: Query current FEC mode from link info
- fec_set: Configure FEC mode on the link. AUTO mode
  defaults to Reed-Solomon FEC.

Signed-off-by: Rakesh Kudurumalla <[email protected]>
---
 drivers/net/cnxk/cnxk_ethdev.c     |  3 +
 drivers/net/cnxk/cnxk_ethdev.h     |  6 ++
 drivers/net/cnxk/cnxk_ethdev_ops.c | 94 ++++++++++++++++++++++++++++++
 3 files changed, 103 insertions(+)

diff --git a/drivers/net/cnxk/cnxk_ethdev.c b/drivers/net/cnxk/cnxk_ethdev.c
index 06d1c9b362..1cb0dd5bf1 100644
--- a/drivers/net/cnxk/cnxk_ethdev.c
+++ b/drivers/net/cnxk/cnxk_ethdev.c
@@ -2138,6 +2138,9 @@ struct eth_dev_ops cnxk_eth_dev_ops = {
        .cman_config_set = cnxk_nix_cman_config_set,
        .cman_config_get = cnxk_nix_cman_config_get,
        .eth_tx_descriptor_dump = cnxk_nix_tx_descriptor_dump,
+       .fec_get_capability = cnxk_nix_fec_get_capability,
+       .fec_get = cnxk_nix_fec_get,
+       .fec_set = cnxk_nix_fec_set,
 };
 
 void
diff --git a/drivers/net/cnxk/cnxk_ethdev.h b/drivers/net/cnxk/cnxk_ethdev.h
index 8691acc642..b1078397d3 100644
--- a/drivers/net/cnxk/cnxk_ethdev.h
+++ b/drivers/net/cnxk/cnxk_ethdev.h
@@ -660,6 +660,12 @@ int cnxk_nix_tm_mark_ip_dscp(struct rte_eth_dev *eth_dev, 
int mark_green,
 int cnxk_nix_tx_descriptor_dump(const struct rte_eth_dev *eth_dev, uint16_t 
qid, uint16_t offset,
                                uint16_t num, FILE *file);
 
+/* FEC */
+int cnxk_nix_fec_get_capability(struct rte_eth_dev *eth_dev,
+                               struct rte_eth_fec_capa *speed_fec_capa, 
unsigned int num);
+int cnxk_nix_fec_get(struct rte_eth_dev *eth_dev, uint32_t *fec_capa);
+int cnxk_nix_fec_set(struct rte_eth_dev *eth_dev, uint32_t fec_capa);
+
 /* MTR */
 int cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops);
 
diff --git a/drivers/net/cnxk/cnxk_ethdev_ops.c 
b/drivers/net/cnxk/cnxk_ethdev_ops.c
index 49e77e49a6..a45721d414 100644
--- a/drivers/net/cnxk/cnxk_ethdev_ops.c
+++ b/drivers/net/cnxk/cnxk_ethdev_ops.c
@@ -1414,3 +1414,97 @@ cnxk_nix_tx_descriptor_dump(const struct rte_eth_dev 
*eth_dev, uint16_t qid, uin
 
        return roc_nix_sq_desc_dump(nix, qid, offset, num, file);
 }
+
+static uint32_t
+cnxk_roc_fec_to_ethdev_capa(int roc_fec)
+{
+       switch (roc_fec) {
+       case ROC_FEC_BASER:
+               return RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
+       case ROC_FEC_RS:
+               return RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+       default:
+               return RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
+       }
+}
+
+static int
+cnxk_ethdev_fec_to_roc(uint32_t fec_capa)
+{
+       if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(RS))
+               return ROC_FEC_RS;
+       if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(BASER))
+               return ROC_FEC_BASER;
+       return ROC_FEC_NONE;
+}
+
+static uint32_t
+cnxk_fec_capa_from_supported(uint64_t supported_fec)
+{
+       uint32_t capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) | 
RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
+
+       if (supported_fec & (1ULL << ROC_FEC_BASER))
+               capa |= RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
+       if (supported_fec & (1ULL << ROC_FEC_RS))
+               capa |= RTE_ETH_FEC_MODE_CAPA_MASK(RS);
+
+       return capa;
+}
+
+int
+cnxk_nix_fec_get_capability(struct rte_eth_dev *eth_dev, struct 
rte_eth_fec_capa *speed_fec_capa,
+                           unsigned int num)
+{
+       struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+       struct roc_nix *nix = &dev->nix;
+       struct roc_nix_link_info link_info;
+       uint64_t supported_fec = 0;
+       int rc;
+
+       rc = roc_nix_mac_fec_supported_get(nix, &supported_fec);
+       if (rc == 0 && supported_fec != 0) {
+               rc = roc_nix_mac_link_info_get(nix, &link_info);
+               if (rc)
+                       return rc;
+
+               if (speed_fec_capa == NULL || num == 0)
+                       return 1;
+
+               speed_fec_capa[0].speed = link_info.speed;
+               speed_fec_capa[0].capa = 
cnxk_fec_capa_from_supported(supported_fec);
+               return 1;
+       }
+
+       return rc;
+}
+
+int
+cnxk_nix_fec_get(struct rte_eth_dev *eth_dev, uint32_t *fec_capa)
+{
+       struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+       struct roc_nix *nix = &dev->nix;
+       struct roc_nix_link_info link_info;
+       int rc;
+
+       rc = roc_nix_mac_link_info_get(nix, &link_info);
+       if (rc)
+               return rc;
+
+       *fec_capa = cnxk_roc_fec_to_ethdev_capa(link_info.fec);
+       return 0;
+}
+
+int
+cnxk_nix_fec_set(struct rte_eth_dev *eth_dev, uint32_t fec_capa)
+{
+       struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+       struct roc_nix *nix = &dev->nix;
+       int roc_fec;
+
+       if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(AUTO))
+               roc_fec = ROC_FEC_RS;
+       else
+               roc_fec = cnxk_ethdev_fec_to_roc(fec_capa);
+
+       return roc_nix_mac_fec_set(nix, roc_fec);
+}
-- 
2.25.1

Reply via email to