From: Ashwin Sekhar T K Date: Tue, 6 Apr 2021 14:41:02 +0000 (+0530) Subject: common/cnxk: support NPA device X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=124ff1a4cbb3318421b03391b2cbc6735410f4bc;p=dpdk.git common/cnxk: support NPA device Add base NPA device support. NPA i.e Network Pool Allocator is HW block that provides HW mempool functionality on Marvell CN9K and CN10K SoC's. NPA by providing HW mempool support, also facilitates Rx and Tx packet alloc and packet free by HW without SW intervention. Signed-off-by: Ashwin Sekhar T K Acked-by: Nithin Dabilpuram --- diff --git a/drivers/common/cnxk/meson.build b/drivers/common/cnxk/meson.build index 17cbc368d1..2aeed3e0f8 100644 --- a/drivers/common/cnxk/meson.build +++ b/drivers/common/cnxk/meson.build @@ -15,6 +15,7 @@ sources = files('roc_dev.c', 'roc_irq.c', 'roc_mbox.c', 'roc_model.c', + 'roc_npa.c', 'roc_platform.c', 'roc_utils.c') includes += include_directories('../../bus/pci') diff --git a/drivers/common/cnxk/roc_api.h b/drivers/common/cnxk/roc_api.h index 27ddc3ad26..9289c68751 100644 --- a/drivers/common/cnxk/roc_api.h +++ b/drivers/common/cnxk/roc_api.h @@ -79,6 +79,9 @@ /* Mbox */ #include "roc_mbox.h" +/* NPA */ +#include "roc_npa.h" + /* Utils */ #include "roc_utils.h" diff --git a/drivers/common/cnxk/roc_dev.c b/drivers/common/cnxk/roc_dev.c index 4cd5978326..a39acc9f6e 100644 --- a/drivers/common/cnxk/roc_dev.c +++ b/drivers/common/cnxk/roc_dev.c @@ -1125,6 +1125,10 @@ dev_init(struct dev *dev, struct plt_pci_device *pci_dev) } dev->mbox_active = 1; + rc = npa_lf_init(dev, pci_dev); + if (rc) + goto iounmap; + /* Setup LMT line base */ rc = dev_lmt_setup(pci_dev, dev); if (rc) @@ -1150,6 +1154,13 @@ dev_fini(struct dev *dev, struct plt_pci_device *pci_dev) struct plt_intr_handle *intr_handle = &pci_dev->intr_handle; struct mbox *mbox; + /* Check if this dev hosts npalf and has 1+ refs */ + if (idev_npa_lf_active(dev) > 1) + return -EAGAIN; + + /* Clear references to this pci dev */ + npa_lf_fini(); + mbox_unregister_irq(pci_dev, dev); if (!dev_is_vf(dev)) diff --git a/drivers/common/cnxk/roc_dev_priv.h b/drivers/common/cnxk/roc_dev_priv.h index d20b089489..910cfb6ecc 100644 --- a/drivers/common/cnxk/roc_dev_priv.h +++ b/drivers/common/cnxk/roc_dev_priv.h @@ -78,6 +78,7 @@ struct dev { dev_intr_t intr; int timer_set; /* ~0 : no alarm handling */ uint64_t hwcap; + struct npa_lf npa; struct mbox *mbox; uint16_t maxvf; struct dev_ops *ops; @@ -85,6 +86,11 @@ struct dev { bool disable_shared_lmt; /* false(default): shared lmt mode enabled */ } __plt_cache_aligned; +struct npa { + struct plt_pci_device *pci_dev; + struct dev dev; +} __plt_cache_aligned; + extern uint16_t dev_rclk_freq; extern uint16_t dev_sclk_freq; diff --git a/drivers/common/cnxk/roc_idev.c b/drivers/common/cnxk/roc_idev.c index 7fbbbdc90d..bf9cce8317 100644 --- a/drivers/common/cnxk/roc_idev.c +++ b/drivers/common/cnxk/roc_idev.c @@ -29,9 +29,76 @@ idev_get_cfg(void) void idev_set_defaults(struct idev_cfg *idev) { + idev->npa = NULL; + idev->npa_pf_func = 0; + idev->max_pools = 128; idev->lmt_pf_func = 0; idev->lmt_base_addr = 0; idev->num_lmtlines = 0; + __atomic_store_n(&idev->npa_refcnt, 0, __ATOMIC_RELEASE); +} + +uint16_t +idev_npa_pffunc_get(void) +{ + struct idev_cfg *idev; + uint16_t npa_pf_func; + + idev = idev_get_cfg(); + npa_pf_func = 0; + if (idev != NULL) + npa_pf_func = idev->npa_pf_func; + + return npa_pf_func; +} + +struct npa_lf * +idev_npa_obj_get(void) +{ + struct idev_cfg *idev; + + idev = idev_get_cfg(); + if (idev && __atomic_load_n(&idev->npa_refcnt, __ATOMIC_ACQUIRE)) + return idev->npa; + + return NULL; +} + +uint32_t +roc_idev_npa_maxpools_get(void) +{ + struct idev_cfg *idev; + uint32_t max_pools; + + idev = idev_get_cfg(); + max_pools = 0; + if (idev != NULL) + max_pools = idev->max_pools; + + return max_pools; +} + +void +roc_idev_npa_maxpools_set(uint32_t max_pools) +{ + struct idev_cfg *idev; + + idev = idev_get_cfg(); + if (idev != NULL) + __atomic_store_n(&idev->max_pools, max_pools, __ATOMIC_RELEASE); +} + +uint16_t +idev_npa_lf_active(struct dev *dev) +{ + struct idev_cfg *idev; + + /* Check if npalf is actively used on this dev */ + idev = idev_get_cfg(); + if (!idev || !idev->npa || idev->npa->mbox != dev->mbox) + return 0; + + return __atomic_load_n(&idev->npa_refcnt, __ATOMIC_ACQUIRE); } uint16_t diff --git a/drivers/common/cnxk/roc_idev.h b/drivers/common/cnxk/roc_idev.h index dff0741941..f2678651fe 100644 --- a/drivers/common/cnxk/roc_idev.h +++ b/drivers/common/cnxk/roc_idev.h @@ -5,6 +5,9 @@ #ifndef _ROC_IDEV_H_ #define _ROC_IDEV_H_ +uint32_t __roc_api roc_idev_npa_maxpools_get(void); +void __roc_api roc_idev_npa_maxpools_set(uint32_t max_pools); + /* LMT */ uint64_t __roc_api roc_idev_lmt_base_addr_get(void); uint16_t __roc_api roc_idev_num_lmtlines_get(void); diff --git a/drivers/common/cnxk/roc_idev_priv.h b/drivers/common/cnxk/roc_idev_priv.h index a096288a33..36cdb330eb 100644 --- a/drivers/common/cnxk/roc_idev_priv.h +++ b/drivers/common/cnxk/roc_idev_priv.h @@ -6,7 +6,12 @@ #define _ROC_IDEV_PRIV_H_ /* Intra device related functions */ +struct npa_lf; struct idev_cfg { + uint16_t npa_pf_func; + struct npa_lf *npa; + uint16_t npa_refcnt; + uint32_t max_pools; uint16_t lmt_pf_func; uint16_t num_lmtlines; uint64_t lmt_base_addr; @@ -16,6 +21,13 @@ struct idev_cfg { struct idev_cfg *idev_get_cfg(void); void idev_set_defaults(struct idev_cfg *idev); +/* idev npa */ +uint16_t idev_npa_pffunc_get(void); +struct npa_lf *idev_npa_obj_get(void); +uint32_t idev_npa_maxpools_get(void); +void idev_npa_maxpools_set(uint32_t max_pools); +uint16_t idev_npa_lf_active(struct dev *dev); + /* idev lmt */ uint16_t idev_lmt_pffunc_get(void); diff --git a/drivers/common/cnxk/roc_npa.c b/drivers/common/cnxk/roc_npa.c new file mode 100644 index 0000000000..2aa726b29f --- /dev/null +++ b/drivers/common/cnxk/roc_npa.c @@ -0,0 +1,318 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2021 Marvell. + */ + +#include "roc_api.h" +#include "roc_priv.h" + +static inline int +npa_attach(struct mbox *mbox) +{ + struct rsrc_attach_req *req; + + req = mbox_alloc_msg_attach_resources(mbox); + if (req == NULL) + return -ENOSPC; + req->modify = true; + req->npalf = true; + + return mbox_process(mbox); +} + +static inline int +npa_detach(struct mbox *mbox) +{ + struct rsrc_detach_req *req; + + req = mbox_alloc_msg_detach_resources(mbox); + if (req == NULL) + return -ENOSPC; + req->partial = true; + req->npalf = true; + + return mbox_process(mbox); +} + +static inline int +npa_get_msix_offset(struct mbox *mbox, uint16_t *npa_msixoff) +{ + struct msix_offset_rsp *msix_rsp; + int rc; + + /* Get NPA MSIX vector offsets */ + mbox_alloc_msg_msix_offset(mbox); + rc = mbox_process_msg(mbox, (void *)&msix_rsp); + if (rc == 0) + *npa_msixoff = msix_rsp->npa_msixoff; + + return rc; +} + +static inline int +npa_lf_alloc(struct npa_lf *lf) +{ + struct mbox *mbox = lf->mbox; + struct npa_lf_alloc_req *req; + struct npa_lf_alloc_rsp *rsp; + int rc; + + req = mbox_alloc_msg_npa_lf_alloc(mbox); + if (req == NULL) + return -ENOSPC; + req->aura_sz = lf->aura_sz; + req->nr_pools = lf->nr_pools; + + rc = mbox_process_msg(mbox, (void *)&rsp); + if (rc) + return NPA_ERR_ALLOC; + + lf->stack_pg_ptrs = rsp->stack_pg_ptrs; + lf->stack_pg_bytes = rsp->stack_pg_bytes; + lf->qints = rsp->qints; + + return 0; +} + +static int +npa_lf_free(struct mbox *mbox) +{ + mbox_alloc_msg_npa_lf_free(mbox); + return mbox_process(mbox); +} + +static inline uint32_t +aura_size_to_u32(uint8_t val) +{ + if (val == NPA_AURA_SZ_0) + return 128; + if (val >= NPA_AURA_SZ_MAX) + return BIT_ULL(20); + + return 1 << (val + 6); +} + +static inline void +pool_count_aura_sz_get(uint32_t *nr_pools, uint8_t *aura_sz) +{ + uint32_t val; + + val = roc_idev_npa_maxpools_get(); + if (val < aura_size_to_u32(NPA_AURA_SZ_128)) + val = 128; + if (val > aura_size_to_u32(NPA_AURA_SZ_1M)) + val = BIT_ULL(20); + + roc_idev_npa_maxpools_set(val); + *nr_pools = val; + *aura_sz = plt_log2_u32(val) - 6; +} + +static int +npa_dev_init(struct npa_lf *lf, uintptr_t base, struct mbox *mbox) +{ + uint32_t i, bmp_sz, nr_pools; + uint8_t aura_sz; + int rc; + + /* Sanity checks */ + if (!lf || !base || !mbox) + return NPA_ERR_PARAM; + + if (base & ROC_AURA_ID_MASK) + return NPA_ERR_BASE_INVALID; + + pool_count_aura_sz_get(&nr_pools, &aura_sz); + if (aura_sz == NPA_AURA_SZ_0 || aura_sz >= NPA_AURA_SZ_MAX) + return NPA_ERR_PARAM; + + memset(lf, 0x0, sizeof(*lf)); + lf->base = base; + lf->aura_sz = aura_sz; + lf->nr_pools = nr_pools; + lf->mbox = mbox; + + rc = npa_lf_alloc(lf); + if (rc) + goto exit; + + bmp_sz = plt_bitmap_get_memory_footprint(nr_pools); + + /* Allocate memory for bitmap */ + lf->npa_bmp_mem = plt_zmalloc(bmp_sz, ROC_ALIGN); + if (lf->npa_bmp_mem == NULL) { + rc = NPA_ERR_ALLOC; + goto lf_free; + } + + /* Initialize pool resource bitmap array */ + lf->npa_bmp = plt_bitmap_init(nr_pools, lf->npa_bmp_mem, bmp_sz); + if (lf->npa_bmp == NULL) { + rc = NPA_ERR_PARAM; + goto bmap_mem_free; + } + + /* Mark all pools available */ + for (i = 0; i < nr_pools; i++) + plt_bitmap_set(lf->npa_bmp, i); + + /* Allocate memory for qint context */ + lf->npa_qint_mem = plt_zmalloc(sizeof(struct npa_qint) * nr_pools, 0); + if (lf->npa_qint_mem == NULL) { + rc = NPA_ERR_ALLOC; + goto bmap_free; + } + + /* Allocate memory for nap_aura_lim memory */ + lf->aura_lim = plt_zmalloc(sizeof(struct npa_aura_lim) * nr_pools, 0); + if (lf->aura_lim == NULL) { + rc = NPA_ERR_ALLOC; + goto qint_free; + } + + /* Init aura start & end limits */ + for (i = 0; i < nr_pools; i++) { + lf->aura_lim[i].ptr_start = UINT64_MAX; + lf->aura_lim[i].ptr_end = 0x0ull; + } + + return 0; + +qint_free: + plt_free(lf->npa_qint_mem); +bmap_free: + plt_bitmap_free(lf->npa_bmp); +bmap_mem_free: + plt_free(lf->npa_bmp_mem); +lf_free: + npa_lf_free(lf->mbox); +exit: + return rc; +} + +static int +npa_dev_fini(struct npa_lf *lf) +{ + if (!lf) + return NPA_ERR_PARAM; + + plt_free(lf->aura_lim); + plt_free(lf->npa_qint_mem); + plt_bitmap_free(lf->npa_bmp); + plt_free(lf->npa_bmp_mem); + + return npa_lf_free(lf->mbox); +} + +int +npa_lf_init(struct dev *dev, struct plt_pci_device *pci_dev) +{ + struct idev_cfg *idev; + uint16_t npa_msixoff; + struct npa_lf *lf; + int rc; + + idev = idev_get_cfg(); + if (idev == NULL) + return NPA_ERR_ALLOC; + + /* Not the first PCI device */ + if (__atomic_fetch_add(&idev->npa_refcnt, 1, __ATOMIC_SEQ_CST) != 0) + return 0; + + rc = npa_attach(dev->mbox); + if (rc) + goto fail; + + rc = npa_get_msix_offset(dev->mbox, &npa_msixoff); + if (rc) + goto npa_detach; + + lf = &dev->npa; + rc = npa_dev_init(lf, dev->bar2 + (RVU_BLOCK_ADDR_NPA << 20), + dev->mbox); + if (rc) + goto npa_detach; + + lf->pf_func = dev->pf_func; + lf->npa_msixoff = npa_msixoff; + lf->intr_handle = &pci_dev->intr_handle; + lf->pci_dev = pci_dev; + + idev->npa_pf_func = dev->pf_func; + idev->npa = lf; + plt_wmb(); + + plt_npa_dbg("npa=%p max_pools=%d pf_func=0x%x msix=0x%x", lf, + roc_idev_npa_maxpools_get(), lf->pf_func, npa_msixoff); + + return 0; + +npa_detach: + npa_detach(dev->mbox); +fail: + __atomic_fetch_sub(&idev->npa_refcnt, 1, __ATOMIC_SEQ_CST); + return rc; +} + +int +npa_lf_fini(void) +{ + struct idev_cfg *idev; + int rc = 0; + + idev = idev_get_cfg(); + if (idev == NULL) + return NPA_ERR_ALLOC; + + /* Not the last PCI device */ + if (__atomic_sub_fetch(&idev->npa_refcnt, 1, __ATOMIC_SEQ_CST) != 0) + return 0; + + rc |= npa_dev_fini(idev->npa); + rc |= npa_detach(idev->npa->mbox); + idev_set_defaults(idev); + + return rc; +} + +int +roc_npa_dev_init(struct roc_npa *roc_npa) +{ + struct plt_pci_device *pci_dev; + struct npa *npa; + struct dev *dev; + int rc; + + if (roc_npa == NULL || roc_npa->pci_dev == NULL) + return NPA_ERR_PARAM; + + PLT_STATIC_ASSERT(sizeof(struct npa) <= ROC_NPA_MEM_SZ); + npa = roc_npa_to_npa_priv(roc_npa); + memset(npa, 0, sizeof(*npa)); + pci_dev = roc_npa->pci_dev; + dev = &npa->dev; + + /* Initialize device */ + rc = dev_init(dev, pci_dev); + if (rc) { + plt_err("Failed to init roc device"); + goto fail; + } + + npa->pci_dev = pci_dev; + dev->drv_inited = true; +fail: + return rc; +} + +int +roc_npa_dev_fini(struct roc_npa *roc_npa) +{ + struct npa *npa = roc_npa_to_npa_priv(roc_npa); + + if (npa == NULL) + return NPA_ERR_PARAM; + + npa->dev.drv_inited = false; + return dev_fini(&npa->dev, npa->pci_dev); +} diff --git a/drivers/common/cnxk/roc_npa.h b/drivers/common/cnxk/roc_npa.h new file mode 100644 index 0000000000..a708725356 --- /dev/null +++ b/drivers/common/cnxk/roc_npa.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2021 Marvell. + */ + +#ifndef _ROC_NPA_H_ +#define _ROC_NPA_H_ + +#define ROC_AURA_ID_MASK (BIT_ULL(16) - 1) + +struct roc_npa { + struct plt_pci_device *pci_dev; + +#define ROC_NPA_MEM_SZ (1 * 1024) + uint8_t reserved[ROC_NPA_MEM_SZ] __plt_cache_aligned; +} __plt_cache_aligned; + +int __roc_api roc_npa_dev_init(struct roc_npa *roc_npa); +int __roc_api roc_npa_dev_fini(struct roc_npa *roc_npa); + +#endif /* _ROC_NPA_H_ */ diff --git a/drivers/common/cnxk/roc_npa_priv.h b/drivers/common/cnxk/roc_npa_priv.h new file mode 100644 index 0000000000..dd6981fc9f --- /dev/null +++ b/drivers/common/cnxk/roc_npa_priv.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2021 Marvell. + */ + +#ifndef _ROC_NPA_PRIV_H_ +#define _ROC_NPA_PRIV_H_ + +enum npa_error_status { + NPA_ERR_PARAM = -512, + NPA_ERR_ALLOC = -513, + NPA_ERR_INVALID_BLOCK_SZ = -514, + NPA_ERR_AURA_ID_ALLOC = -515, + NPA_ERR_AURA_POOL_INIT = -516, + NPA_ERR_AURA_POOL_FINI = -517, + NPA_ERR_BASE_INVALID = -518, + NPA_ERR_DEVICE_NOT_BOUNDED = -519, +}; + +struct npa_lf { + struct plt_intr_handle *intr_handle; + struct npa_aura_lim *aura_lim; + struct plt_pci_device *pci_dev; + struct plt_bitmap *npa_bmp; + struct mbox *mbox; + uint32_t stack_pg_ptrs; + uint32_t stack_pg_bytes; + uint16_t npa_msixoff; + void *npa_qint_mem; + void *npa_bmp_mem; + uint32_t nr_pools; + uint16_t pf_func; + uint8_t aura_sz; + uint32_t qints; + uintptr_t base; +}; + +struct npa_qint { + struct npa_lf *lf; + uint8_t qintx; +}; + +struct npa_aura_lim { + uint64_t ptr_start; + uint64_t ptr_end; +}; + +struct dev; + +static inline struct npa * +roc_npa_to_npa_priv(struct roc_npa *roc_npa) +{ + return (struct npa *)&roc_npa->reserved[0]; +} + +/* NPA lf */ +int npa_lf_init(struct dev *dev, struct plt_pci_device *pci_dev); +int npa_lf_fini(void); + +#endif /* _ROC_NPA_PRIV_H_ */ diff --git a/drivers/common/cnxk/roc_platform.c b/drivers/common/cnxk/roc_platform.c index 4147f592a7..444d22346d 100644 --- a/drivers/common/cnxk/roc_platform.c +++ b/drivers/common/cnxk/roc_platform.c @@ -58,3 +58,4 @@ roc_plt_init(void) RTE_LOG_REGISTER(cnxk_logtype_base, pmd.cnxk.base, NOTICE); RTE_LOG_REGISTER(cnxk_logtype_mbox, pmd.cnxk.mbox, NOTICE); +RTE_LOG_REGISTER(cnxk_logtype_npa, pmd.mempool.cnxk, NOTICE); diff --git a/drivers/common/cnxk/roc_platform.h b/drivers/common/cnxk/roc_platform.h index 84c2da4f58..69ec60023c 100644 --- a/drivers/common/cnxk/roc_platform.h +++ b/drivers/common/cnxk/roc_platform.h @@ -134,6 +134,7 @@ /* Log */ extern int cnxk_logtype_base; extern int cnxk_logtype_mbox; +extern int cnxk_logtype_npa; #define plt_err(fmt, args...) \ RTE_LOG(ERR, PMD, "%s():%u " fmt "\n", __func__, __LINE__, ##args) @@ -151,6 +152,7 @@ extern int cnxk_logtype_mbox; #define plt_base_dbg(fmt, ...) plt_dbg(base, fmt, ##__VA_ARGS__) #define plt_mbox_dbg(fmt, ...) plt_dbg(mbox, fmt, ##__VA_ARGS__) +#define plt_npa_dbg(fmt, ...) plt_dbg(npa, fmt, ##__VA_ARGS__) #ifdef __cplusplus #define CNXK_PCI_ID(subsystem_dev, dev) \ diff --git a/drivers/common/cnxk/roc_priv.h b/drivers/common/cnxk/roc_priv.h index 2df2d66128..21599dc571 100644 --- a/drivers/common/cnxk/roc_priv.h +++ b/drivers/common/cnxk/roc_priv.h @@ -11,6 +11,9 @@ /* Mbox */ #include "roc_mbox_priv.h" +/* NPA */ +#include "roc_npa_priv.h" + /* Dev */ #include "roc_dev_priv.h" diff --git a/drivers/common/cnxk/roc_utils.c b/drivers/common/cnxk/roc_utils.c index b21064a3a3..b5d8f0bb13 100644 --- a/drivers/common/cnxk/roc_utils.c +++ b/drivers/common/cnxk/roc_utils.c @@ -11,9 +11,31 @@ roc_error_msg_get(int errorcode) const char *err_msg; switch (errorcode) { + case NPA_ERR_PARAM: case UTIL_ERR_PARAM: err_msg = "Invalid parameter"; break; + case NPA_ERR_ALLOC: + err_msg = "NPA alloc failed"; + break; + case NPA_ERR_INVALID_BLOCK_SZ: + err_msg = "NPA invalid block size"; + break; + case NPA_ERR_AURA_ID_ALLOC: + err_msg = "NPA aura id alloc failed"; + break; + case NPA_ERR_AURA_POOL_INIT: + err_msg = "NPA aura pool init failed"; + break; + case NPA_ERR_AURA_POOL_FINI: + err_msg = "NPA aura pool fini failed"; + break; + case NPA_ERR_BASE_INVALID: + err_msg = "NPA invalid base"; + break; + case NPA_ERR_DEVICE_NOT_BOUNDED: + err_msg = "NPA device is not bounded"; + break; case UTIL_ERR_FS: err_msg = "file operation failed"; break; diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map index 369cff3315..04a0d33d6e 100644 --- a/drivers/common/cnxk/version.map +++ b/drivers/common/cnxk/version.map @@ -3,11 +3,16 @@ INTERNAL { cnxk_logtype_base; cnxk_logtype_mbox; + cnxk_logtype_npa; roc_clk_freq_get; roc_error_msg_get; roc_idev_lmt_base_addr_get; + roc_idev_npa_maxpools_get; + roc_idev_npa_maxpools_set; roc_idev_num_lmtlines_get; roc_model; + roc_npa_dev_fini; + roc_npa_dev_init; roc_plt_init; roc_plt_init_cb_register;