From 309b553c26fa1820d6a38272d8b3e2a2e54ca082 Mon Sep 17 00:00:00 2001 From: Pavan Nikhilesh Date: Tue, 6 Apr 2021 20:11:43 +0530 Subject: [PATCH] common/cnxk: support TIM IRQ Add TIM LF IRQ register and un-register functions. Signed-off-by: Pavan Nikhilesh Acked-by: Nithin Dabilpuram --- drivers/common/cnxk/meson.build | 1 + drivers/common/cnxk/roc_tim.c | 51 ++++++++++++++ drivers/common/cnxk/roc_tim_irq.c | 104 +++++++++++++++++++++++++++++ drivers/common/cnxk/roc_tim_priv.h | 9 +++ 4 files changed, 165 insertions(+) create mode 100644 drivers/common/cnxk/roc_tim_irq.c diff --git a/drivers/common/cnxk/meson.build b/drivers/common/cnxk/meson.build index 1b0217847c..4573d1388a 100644 --- a/drivers/common/cnxk/meson.build +++ b/drivers/common/cnxk/meson.build @@ -43,5 +43,6 @@ sources = files('roc_dev.c', 'roc_sso_debug.c', 'roc_sso_irq.c', 'roc_tim.c', + 'roc_tim_irq.c', 'roc_utils.c') includes += include_directories('../../bus/pci') diff --git a/drivers/common/cnxk/roc_tim.c b/drivers/common/cnxk/roc_tim.c index 37faa3704b..387164bb1d 100644 --- a/drivers/common/cnxk/roc_tim.c +++ b/drivers/common/cnxk/roc_tim.c @@ -5,6 +5,25 @@ #include "roc_api.h" #include "roc_priv.h" +static int +tim_fill_msix(struct roc_tim *roc_tim, uint16_t nb_ring) +{ + struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev; + struct tim *tim = roc_tim_to_tim_priv(roc_tim); + struct msix_offset_rsp *rsp; + int i, rc; + + mbox_alloc_msg_msix_offset(dev->mbox); + rc = mbox_process_msg(dev->mbox, (void **)&rsp); + if (rc < 0) + return rc; + + for (i = 0; i < nb_ring; i++) + tim->tim_msix_offsets[i] = rsp->timlf_msixoff[i]; + + return 0; +} + static void tim_err_desc(int rc) { @@ -158,6 +177,8 @@ int roc_tim_lf_alloc(struct roc_tim *roc_tim, uint8_t ring_id, uint64_t *clk) { struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso); + struct tim *tim = roc_tim_to_tim_priv(roc_tim); + struct tim_ring_req *free_req; struct tim_lf_alloc_req *req; struct tim_lf_alloc_rsp *rsp; struct dev *dev = &sso->dev; @@ -179,6 +200,17 @@ roc_tim_lf_alloc(struct roc_tim *roc_tim, uint8_t ring_id, uint64_t *clk) if (clk) *clk = rsp->tenns_clk; + rc = tim_register_irq_priv(roc_tim, &sso->pci_dev->intr_handle, ring_id, + tim->tim_msix_offsets[ring_id]); + if (rc < 0) { + plt_tim_dbg("Failed to register Ring[%d] IRQ", ring_id); + free_req = mbox_alloc_msg_tim_lf_free(dev->mbox); + if (free_req == NULL) + return -ENOSPC; + free_req->ring = ring_id; + mbox_process(dev->mbox); + } + return rc; } @@ -186,10 +218,14 @@ int roc_tim_lf_free(struct roc_tim *roc_tim, uint8_t ring_id) { struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso); + struct tim *tim = roc_tim_to_tim_priv(roc_tim); struct dev *dev = &sso->dev; struct tim_ring_req *req; int rc = -ENOSPC; + tim_unregister_irq_priv(roc_tim, &sso->pci_dev->intr_handle, ring_id, + tim->tim_msix_offsets[ring_id]); + req = mbox_alloc_msg_tim_lf_free(dev->mbox); if (req == NULL) return rc; @@ -208,6 +244,7 @@ int roc_tim_init(struct roc_tim *roc_tim) { struct rsrc_attach_req *attach_req; + struct rsrc_detach_req *detach_req; struct free_rsrcs_rsp *free_rsrc; struct dev *dev; uint16_t nb_lfs; @@ -245,6 +282,20 @@ roc_tim_init(struct roc_tim *roc_tim) return 0; } + rc = tim_fill_msix(roc_tim, nb_lfs); + if (rc < 0) { + plt_err("Unable to get TIM MSIX vectors"); + + detach_req = mbox_alloc_msg_detach_resources(dev->mbox); + if (detach_req == NULL) + return -ENOSPC; + detach_req->partial = true; + detach_req->timlfs = true; + mbox_process(dev->mbox); + + return 0; + } + return nb_lfs; } diff --git a/drivers/common/cnxk/roc_tim_irq.c b/drivers/common/cnxk/roc_tim_irq.c new file mode 100644 index 0000000000..7bd3e76549 --- /dev/null +++ b/drivers/common/cnxk/roc_tim_irq.c @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2021 Marvell. + */ + +#include "roc_api.h" +#include "roc_priv.h" + +static void +tim_lf_irq(void *param) +{ + uintptr_t base = (uintptr_t)param; + uint64_t intr; + uint8_t ring; + + ring = (base >> 12) & 0xFF; + + intr = plt_read64(base + TIM_LF_NRSPERR_INT); + plt_err("TIM RING %d TIM_LF_NRSPERR_INT=0x%" PRIx64 "", ring, intr); + intr = plt_read64(base + TIM_LF_RAS_INT); + plt_err("TIM RING %d TIM_LF_RAS_INT=0x%" PRIx64 "", ring, intr); + + /* Clear interrupt */ + plt_write64(intr, base + TIM_LF_NRSPERR_INT); + plt_write64(intr, base + TIM_LF_RAS_INT); +} + +static int +tim_lf_register_irq(uintptr_t base, struct plt_intr_handle *handle, + uint16_t msix_offset) +{ + unsigned int vec; + int rc; + + vec = msix_offset + TIM_LF_INT_VEC_NRSPERR_INT; + + /* Clear err interrupt */ + plt_write64(~0ull, base + TIM_LF_NRSPERR_INT); + /* Set used interrupt vectors */ + rc = dev_irq_register(handle, tim_lf_irq, (void *)base, vec); + /* Enable hw interrupt */ + plt_write64(~0ull, base + TIM_LF_NRSPERR_INT_ENA_W1S); + + vec = msix_offset + TIM_LF_INT_VEC_RAS_INT; + + /* Clear err interrupt */ + plt_write64(~0ull, base + TIM_LF_RAS_INT); + /* Set used interrupt vectors */ + rc = dev_irq_register(handle, tim_lf_irq, (void *)base, vec); + /* Enable hw interrupt */ + plt_write64(~0ull, base + TIM_LF_RAS_INT_ENA_W1S); + + return rc; +} + +int +tim_register_irq_priv(struct roc_tim *roc_tim, struct plt_intr_handle *handle, + uint8_t ring_id, uint16_t msix_offset) +{ + struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev; + uintptr_t base; + + if (msix_offset == MSIX_VECTOR_INVALID) { + plt_err("Invalid MSIX offset for TIM LF %d", ring_id); + return TIM_ERR_PARAM; + } + + base = dev->bar2 + (RVU_BLOCK_ADDR_TIM << 20 | ring_id << 12); + return tim_lf_register_irq(base, handle, msix_offset); +} + +static void +tim_lf_unregister_irq(uintptr_t base, struct plt_intr_handle *handle, + uint16_t msix_offset) +{ + unsigned int vec; + + vec = msix_offset + TIM_LF_INT_VEC_NRSPERR_INT; + + /* Clear err interrupt */ + plt_write64(~0ull, base + TIM_LF_NRSPERR_INT_ENA_W1C); + dev_irq_unregister(handle, tim_lf_irq, (void *)base, vec); + + vec = msix_offset + TIM_LF_INT_VEC_RAS_INT; + + /* Clear err interrupt */ + plt_write64(~0ull, base + TIM_LF_RAS_INT_ENA_W1C); + dev_irq_unregister(handle, tim_lf_irq, (void *)base, vec); +} + +void +tim_unregister_irq_priv(struct roc_tim *roc_tim, struct plt_intr_handle *handle, + uint8_t ring_id, uint16_t msix_offset) +{ + struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev; + uintptr_t base; + + if (msix_offset == MSIX_VECTOR_INVALID) { + plt_err("Invalid MSIX offset for TIM LF %d", ring_id); + return; + } + + base = dev->bar2 + (RVU_BLOCK_ADDR_TIM << 20 | ring_id << 12); + tim_lf_unregister_irq(base, handle, msix_offset); +} diff --git a/drivers/common/cnxk/roc_tim_priv.h b/drivers/common/cnxk/roc_tim_priv.h index 08697f6e29..cc083d2b4a 100644 --- a/drivers/common/cnxk/roc_tim_priv.h +++ b/drivers/common/cnxk/roc_tim_priv.h @@ -6,6 +6,7 @@ #define _ROC_TIM_PRIV_H_ struct tim { + uint16_t tim_msix_offsets[MAX_RVU_BLKLF_CNT]; }; enum tim_err_status { @@ -18,4 +19,12 @@ roc_tim_to_tim_priv(struct roc_tim *roc_tim) return (struct tim *)&roc_tim->reserved[0]; } +/* TIM IRQ*/ +int tim_register_irq_priv(struct roc_tim *roc_tim, + struct plt_intr_handle *handle, uint8_t ring_id, + uint16_t msix_offset); +void tim_unregister_irq_priv(struct roc_tim *roc_tim, + struct plt_intr_handle *handle, uint8_t ring_id, + uint16_t msix_offset); + #endif /* _ROC_TIM_PRIV_H_ */ -- 2.20.1