--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#include "roc_api.h"
+#include "roc_priv.h"
+
+bool
+roc_nix_is_lbk(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+
+ return nix->lbk_link;
+}
+
+int
+roc_nix_get_base_chan(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+
+ return nix->rx_chan_base;
+}
+
+uint16_t
+roc_nix_get_vwqe_interval(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+
+ return nix->vwqe_interval;
+}
+
+bool
+roc_nix_is_sdp(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+
+ return nix->sdp_link;
+}
+
+bool
+roc_nix_is_pf(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+
+ return !dev_is_vf(&nix->dev);
+}
+
+int
+roc_nix_get_pf(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct dev *dev = &nix->dev;
+
+ return dev_get_pf(dev->pf_func);
+}
+
+int
+roc_nix_get_vf(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct dev *dev = &nix->dev;
+
+ return dev_get_vf(dev->pf_func);
+}
+
+bool
+roc_nix_is_vf_or_sdp(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+
+ return (dev_is_vf(&nix->dev) != 0) || roc_nix_is_sdp(roc_nix);
+}
+
+uint16_t
+roc_nix_get_pf_func(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct dev *dev = &nix->dev;
+
+ return dev->pf_func;
+}
+
+int
+roc_nix_max_pkt_len(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+
+ if (roc_model_is_cn9k())
+ return NIX_CN9K_MAX_HW_FRS;
+
+ if (nix->lbk_link || roc_nix_is_sdp(roc_nix))
+ return NIX_LBK_MAX_HW_FRS;
+
+ return NIX_RPM_MAX_HW_FRS;
+}
+
+int
+roc_nix_lf_alloc(struct roc_nix *roc_nix, uint32_t nb_rxq, uint32_t nb_txq,
+ uint64_t rx_cfg)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct mbox *mbox = (&nix->dev)->mbox;
+ struct nix_lf_alloc_req *req;
+ struct nix_lf_alloc_rsp *rsp;
+ int rc = -ENOSPC;
+
+ req = mbox_alloc_msg_nix_lf_alloc(mbox);
+ if (req == NULL)
+ return rc;
+ req->rq_cnt = nb_rxq;
+ req->sq_cnt = nb_txq;
+ req->cq_cnt = nb_rxq;
+ /* XQESZ can be W64 or W16 */
+ req->xqe_sz = NIX_XQESZ_W16;
+ req->rss_sz = nix->reta_sz;
+ req->rss_grps = ROC_NIX_RSS_GRPS;
+ req->npa_func = idev_npa_pffunc_get();
+ req->rx_cfg = rx_cfg;
+
+ if (!roc_nix->rss_tag_as_xor)
+ req->flags = NIX_LF_RSS_TAG_LSB_AS_ADDER;
+
+ rc = mbox_process_msg(mbox, (void *)&rsp);
+ if (rc)
+ goto fail;
+
+ nix->sqb_size = rsp->sqb_size;
+ nix->tx_chan_base = rsp->tx_chan_base;
+ nix->rx_chan_base = rsp->rx_chan_base;
+ if (roc_nix_is_lbk(roc_nix) && roc_nix->enable_loop)
+ nix->tx_chan_base = rsp->rx_chan_base;
+ nix->rx_chan_cnt = rsp->rx_chan_cnt;
+ nix->tx_chan_cnt = rsp->tx_chan_cnt;
+ nix->lso_tsov4_idx = rsp->lso_tsov4_idx;
+ nix->lso_tsov6_idx = rsp->lso_tsov6_idx;
+ nix->lf_tx_stats = rsp->lf_tx_stats;
+ nix->lf_rx_stats = rsp->lf_rx_stats;
+ nix->cints = rsp->cints;
+ roc_nix->cints = rsp->cints;
+ nix->qints = rsp->qints;
+ nix->ptp_en = rsp->hw_rx_tstamp_en;
+ roc_nix->rx_ptp_ena = rsp->hw_rx_tstamp_en;
+ nix->cgx_links = rsp->cgx_links;
+ nix->lbk_links = rsp->lbk_links;
+ nix->sdp_links = rsp->sdp_links;
+ nix->tx_link = rsp->tx_link;
+ nix->nb_rx_queues = nb_rxq;
+ nix->nb_tx_queues = nb_txq;
+ nix->sqs = plt_zmalloc(sizeof(struct roc_nix_sq *) * nb_txq, 0);
+ if (!nix->sqs)
+ return -ENOMEM;
+fail:
+ return rc;
+}
+
+int
+roc_nix_lf_free(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct mbox *mbox = (&nix->dev)->mbox;
+ struct nix_lf_free_req *req;
+ struct ndc_sync_op *ndc_req;
+ int rc = -ENOSPC;
+
+ plt_free(nix->sqs);
+ nix->sqs = NULL;
+
+ /* Sync NDC-NIX for LF */
+ ndc_req = mbox_alloc_msg_ndc_sync_op(mbox);
+ if (ndc_req == NULL)
+ return rc;
+ ndc_req->nix_lf_tx_sync = 1;
+ ndc_req->nix_lf_rx_sync = 1;
+ rc = mbox_process(mbox);
+ if (rc)
+ plt_err("Error on NDC-NIX-[TX, RX] LF sync, rc %d", rc);
+
+ req = mbox_alloc_msg_nix_lf_free(mbox);
+ if (req == NULL)
+ return -ENOSPC;
+ /* Let AF driver free all this nix lf's
+ * NPC entries allocated using NPC MBOX.
+ */
+ req->flags = 0;
+
+ return mbox_process(mbox);
+}
+
+static inline int
+nix_lf_attach(struct dev *dev)
+{
+ struct mbox *mbox = dev->mbox;
+ struct rsrc_attach_req *req;
+ int rc = -ENOSPC;
+
+ /* Attach NIX(lf) */
+ req = mbox_alloc_msg_attach_resources(mbox);
+ if (req == NULL)
+ return rc;
+ req->modify = true;
+ req->nixlf = true;
+
+ return mbox_process(mbox);
+}
+
+static inline int
+nix_lf_get_msix_offset(struct dev *dev, struct nix *nix)
+{
+ struct msix_offset_rsp *msix_rsp;
+ struct mbox *mbox = dev->mbox;
+ int rc;
+
+ /* Get MSIX vector offsets */
+ mbox_alloc_msg_msix_offset(mbox);
+ rc = mbox_process_msg(mbox, (void *)&msix_rsp);
+ if (rc == 0)
+ nix->msixoff = msix_rsp->nix_msixoff;
+
+ return rc;
+}
+
+static inline int
+nix_lf_detach(struct nix *nix)
+{
+ struct mbox *mbox = (&nix->dev)->mbox;
+ struct rsrc_detach_req *req;
+ int rc = -ENOSPC;
+
+ req = mbox_alloc_msg_detach_resources(mbox);
+ if (req == NULL)
+ return rc;
+ req->partial = true;
+ req->nixlf = true;
+
+ return mbox_process(mbox);
+}
+
+static int
+roc_nix_get_hw_info(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ struct mbox *mbox = (&nix->dev)->mbox;
+ struct nix_hw_info *hw_info;
+ int rc;
+
+ mbox_alloc_msg_nix_get_hw_info(mbox);
+ rc = mbox_process_msg(mbox, (void *)&hw_info);
+ if (rc == 0)
+ nix->vwqe_interval = hw_info->vwqe_delay;
+
+ return rc;
+}
+
+static void
+sdp_lbk_id_update(struct plt_pci_device *pci_dev, struct nix *nix)
+{
+ nix->sdp_link = false;
+ nix->lbk_link = false;
+
+ /* Update SDP/LBK link based on PCI device id */
+ switch (pci_dev->id.device_id) {
+ case PCI_DEVID_CNXK_RVU_SDP_PF:
+ case PCI_DEVID_CNXK_RVU_SDP_VF:
+ nix->sdp_link = true;
+ break;
+ case PCI_DEVID_CNXK_RVU_AF_VF:
+ nix->lbk_link = true;
+ break;
+ default:
+ break;
+ }
+}
+
+static inline uint64_t
+nix_get_blkaddr(struct dev *dev)
+{
+ uint64_t reg;
+
+ /* Reading the discovery register to know which NIX is the LF
+ * attached to.
+ */
+ reg = plt_read64(dev->bar2 +
+ RVU_PF_BLOCK_ADDRX_DISC(RVU_BLOCK_ADDR_NIX0));
+
+ return reg & 0x1FFULL ? RVU_BLOCK_ADDR_NIX0 : RVU_BLOCK_ADDR_NIX1;
+}
+
+int
+roc_nix_dev_init(struct roc_nix *roc_nix)
+{
+ enum roc_nix_rss_reta_sz reta_sz;
+ struct plt_pci_device *pci_dev;
+ uint16_t max_sqb_count;
+ uint64_t blkaddr;
+ struct dev *dev;
+ struct nix *nix;
+ int rc;
+
+ if (roc_nix == NULL || roc_nix->pci_dev == NULL)
+ return NIX_ERR_PARAM;
+
+ reta_sz = roc_nix->reta_sz;
+ if (reta_sz != 0 && reta_sz != 64 && reta_sz != 128 && reta_sz != 256)
+ return NIX_ERR_PARAM;
+
+ if (reta_sz == 0)
+ reta_sz = ROC_NIX_RSS_RETA_SZ_64;
+
+ max_sqb_count = roc_nix->max_sqb_count;
+ max_sqb_count = PLT_MIN(max_sqb_count, NIX_MAX_SQB);
+ max_sqb_count = PLT_MAX(max_sqb_count, NIX_MIN_SQB);
+ roc_nix->max_sqb_count = max_sqb_count;
+
+ PLT_STATIC_ASSERT(sizeof(struct nix) <= ROC_NIX_MEM_SZ);
+ nix = roc_nix_to_nix_priv(roc_nix);
+ pci_dev = roc_nix->pci_dev;
+ dev = &nix->dev;
+
+ if (nix->dev.drv_inited)
+ return 0;
+
+ if (dev->mbox_active)
+ goto skip_dev_init;
+
+ memset(nix, 0, sizeof(*nix));
+ /* Initialize device */
+ rc = dev_init(dev, pci_dev);
+ if (rc) {
+ plt_err("Failed to init roc device");
+ goto fail;
+ }
+
+skip_dev_init:
+ dev->roc_nix = roc_nix;
+
+ nix->lmt_base = dev->lmt_base;
+ /* Expose base LMT line address for
+ * "Per Core LMT line" mode.
+ */
+ roc_nix->lmt_base = dev->lmt_base;
+
+ /* Attach NIX LF */
+ rc = nix_lf_attach(dev);
+ if (rc)
+ goto dev_fini;
+
+ blkaddr = nix_get_blkaddr(dev);
+ nix->is_nix1 = (blkaddr == RVU_BLOCK_ADDR_NIX1);
+
+ /* Calculating base address based on which NIX block LF
+ * is attached to.
+ */
+ nix->base = dev->bar2 + (blkaddr << 20);
+
+ /* Get NIX MSIX offset */
+ rc = nix_lf_get_msix_offset(dev, nix);
+ if (rc)
+ goto lf_detach;
+
+ /* Update nix context */
+ sdp_lbk_id_update(pci_dev, nix);
+ nix->pci_dev = pci_dev;
+ nix->reta_sz = reta_sz;
+ nix->mtu = ROC_NIX_DEFAULT_HW_FRS;
+
+ /* Get NIX HW info */
+ roc_nix_get_hw_info(roc_nix);
+ nix->dev.drv_inited = true;
+
+ return 0;
+lf_detach:
+ nix_lf_detach(nix);
+dev_fini:
+ rc |= dev_fini(dev, pci_dev);
+fail:
+ return rc;
+}
+
+int
+roc_nix_dev_fini(struct roc_nix *roc_nix)
+{
+ struct nix *nix = roc_nix_to_nix_priv(roc_nix);
+ int rc = 0;
+
+ if (nix == NULL)
+ return NIX_ERR_PARAM;
+
+ if (!nix->dev.drv_inited)
+ goto fini;
+
+ rc = nix_lf_detach(nix);
+ nix->dev.drv_inited = false;
+fini:
+ rc |= dev_fini(&nix->dev, nix->pci_dev);
+ return rc;
+}
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#ifndef _ROC_NIX_H_
+#define _ROC_NIX_H_
+
+/* Constants */
+enum roc_nix_rss_reta_sz {
+ ROC_NIX_RSS_RETA_SZ_64 = 64,
+ ROC_NIX_RSS_RETA_SZ_128 = 128,
+ ROC_NIX_RSS_RETA_SZ_256 = 256,
+};
+
+enum roc_nix_sq_max_sqe_sz {
+ roc_nix_maxsqesz_w16 = NIX_MAXSQESZ_W16,
+ roc_nix_maxsqesz_w8 = NIX_MAXSQESZ_W8,
+};
+
+/* NIX LF RX offload configuration flags.
+ * These are input flags to roc_nix_lf_alloc:rx_cfg
+ */
+#define ROC_NIX_LF_RX_CFG_DROP_RE BIT_ULL(32)
+#define ROC_NIX_LF_RX_CFG_L2_LEN_ERR BIT_ULL(33)
+#define ROC_NIX_LF_RX_CFG_IP6_UDP_OPT BIT_ULL(34)
+#define ROC_NIX_LF_RX_CFG_DIS_APAD BIT_ULL(35)
+#define ROC_NIX_LF_RX_CFG_CSUM_IL4 BIT_ULL(36)
+#define ROC_NIX_LF_RX_CFG_CSUM_OL4 BIT_ULL(37)
+#define ROC_NIX_LF_RX_CFG_LEN_IL4 BIT_ULL(38)
+#define ROC_NIX_LF_RX_CFG_LEN_IL3 BIT_ULL(39)
+#define ROC_NIX_LF_RX_CFG_LEN_OL4 BIT_ULL(40)
+#define ROC_NIX_LF_RX_CFG_LEN_OL3 BIT_ULL(41)
+
+/* Group 0 will be used for RSS, 1 -7 will be used for npc_flow RSS action*/
+#define ROC_NIX_RSS_GROUP_DEFAULT 0
+#define ROC_NIX_RSS_GRPS 8
+#define ROC_NIX_RSS_RETA_MAX ROC_NIX_RSS_RETA_SZ_256
+#define ROC_NIX_RSS_KEY_LEN 48 /* 352 Bits */
+
+#define ROC_NIX_DEFAULT_HW_FRS 1514
+
+#define ROC_NIX_VWQE_MAX_SIZE_LOG2 11
+#define ROC_NIX_VWQE_MIN_SIZE_LOG2 2
+struct roc_nix {
+ /* Input parameters */
+ struct plt_pci_device *pci_dev;
+ uint16_t port_id;
+ bool rss_tag_as_xor;
+ uint16_t max_sqb_count;
+ enum roc_nix_rss_reta_sz reta_sz;
+ bool enable_loop;
+ /* End of input parameters */
+ /* LMT line base for "Per Core Tx LMT line" mode*/
+ uintptr_t lmt_base;
+ bool io_enabled;
+ bool rx_ptp_ena;
+ uint16_t cints;
+
+#define ROC_NIX_MEM_SZ (6 * 1024)
+ uint8_t reserved[ROC_NIX_MEM_SZ] __plt_cache_aligned;
+} __plt_cache_aligned;
+
+/* Dev */
+int __roc_api roc_nix_dev_init(struct roc_nix *roc_nix);
+int __roc_api roc_nix_dev_fini(struct roc_nix *roc_nix);
+
+/* Type */
+bool __roc_api roc_nix_is_lbk(struct roc_nix *roc_nix);
+bool __roc_api roc_nix_is_sdp(struct roc_nix *roc_nix);
+bool __roc_api roc_nix_is_pf(struct roc_nix *roc_nix);
+bool __roc_api roc_nix_is_vf_or_sdp(struct roc_nix *roc_nix);
+int __roc_api roc_nix_get_base_chan(struct roc_nix *roc_nix);
+int __roc_api roc_nix_get_pf(struct roc_nix *roc_nix);
+int __roc_api roc_nix_get_vf(struct roc_nix *roc_nix);
+uint16_t __roc_api roc_nix_get_pf_func(struct roc_nix *roc_nix);
+uint16_t __roc_api roc_nix_get_vwqe_interval(struct roc_nix *roc_nix);
+int __roc_api roc_nix_max_pkt_len(struct roc_nix *roc_nix);
+
+/* LF ops */
+int __roc_api roc_nix_lf_alloc(struct roc_nix *roc_nix, uint32_t nb_rxq,
+ uint32_t nb_txq, uint64_t rx_cfg);
+int __roc_api roc_nix_lf_free(struct roc_nix *roc_nix);
+
+#endif /* _ROC_NIX_H_ */
--- /dev/null
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#ifndef _ROC_NIX_PRIV_H_
+#define _ROC_NIX_PRIV_H_
+
+/* Constants */
+#define NIX_CQ_ENTRY_SZ 128
+#define NIX_CQ_ENTRY64_SZ 512
+#define NIX_CQ_ALIGN ((uint16_t)512)
+#define NIX_MAX_SQB ((uint16_t)512)
+#define NIX_DEF_SQB ((uint16_t)16)
+#define NIX_MIN_SQB ((uint16_t)8)
+#define NIX_SQB_LIST_SPACE ((uint16_t)2)
+#define NIX_SQB_LOWER_THRESH ((uint16_t)70)
+
+/* Apply BP/DROP when CQ is 95% full */
+#define NIX_CQ_THRESH_LEVEL (5 * 256 / 100)
+
+struct nix {
+ uint16_t reta[ROC_NIX_RSS_GRPS][ROC_NIX_RSS_RETA_MAX];
+ enum roc_nix_rss_reta_sz reta_sz;
+ struct plt_pci_device *pci_dev;
+ uint16_t bpid[NIX_MAX_CHAN];
+ struct roc_nix_sq **sqs;
+ uint16_t vwqe_interval;
+ uint16_t tx_chan_base;
+ uint16_t rx_chan_base;
+ uint16_t nb_rx_queues;
+ uint16_t nb_tx_queues;
+ uint8_t lso_tsov6_idx;
+ uint8_t lso_tsov4_idx;
+ uint8_t lf_rx_stats;
+ uint8_t lf_tx_stats;
+ uint8_t rx_chan_cnt;
+ uint8_t rss_alg_idx;
+ uint8_t tx_chan_cnt;
+ uintptr_t lmt_base;
+ uint8_t cgx_links;
+ uint8_t lbk_links;
+ uint8_t sdp_links;
+ uint8_t tx_link;
+ uint16_t sqb_size;
+ /* Without FCS, with L2 overhead */
+ uint16_t mtu;
+ uint16_t chan_cnt;
+ uint16_t msixoff;
+ uint8_t rx_pause;
+ uint8_t tx_pause;
+ struct dev dev;
+ uint16_t cints;
+ uint16_t qints;
+ uintptr_t base;
+ bool sdp_link;
+ bool lbk_link;
+ bool ptp_en;
+ bool is_nix1;
+
+} __plt_cache_aligned;
+
+enum nix_err_status {
+ NIX_ERR_PARAM = -2048,
+ NIX_ERR_NO_MEM,
+ NIX_ERR_INVALID_RANGE,
+ NIX_ERR_INTERNAL,
+ NIX_ERR_OP_NOTSUP,
+ NIX_ERR_QUEUE_INVALID_RANGE,
+ NIX_ERR_AQ_READ_FAILED,
+ NIX_ERR_AQ_WRITE_FAILED,
+ NIX_ERR_NDC_SYNC,
+};
+
+enum nix_q_size {
+ nix_q_size_16, /* 16 entries */
+ nix_q_size_64, /* 64 entries */
+ nix_q_size_256,
+ nix_q_size_1K,
+ nix_q_size_4K,
+ nix_q_size_16K,
+ nix_q_size_64K,
+ nix_q_size_256K,
+ nix_q_size_1M, /* Million entries */
+ nix_q_size_max
+};
+
+static inline struct nix *
+roc_nix_to_nix_priv(struct roc_nix *roc_nix)
+{
+ return (struct nix *)&roc_nix->reserved[0];
+}
+
+static inline struct roc_nix *
+nix_priv_to_roc_nix(struct nix *nix)
+{
+ return (struct roc_nix *)((char *)nix -
+ offsetof(struct roc_nix, reserved));
+}
+
+#endif /* _ROC_NIX_PRIV_H_ */