common/cnxk: support TIM IRQ
authorPavan Nikhilesh <pbhagavatula@marvell.com>
Tue, 6 Apr 2021 14:41:43 +0000 (20:11 +0530)
committerJerin Jacob <jerinj@marvell.com>
Fri, 9 Apr 2021 06:32:24 +0000 (08:32 +0200)
Add TIM LF IRQ register and un-register functions.

Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>
Acked-by: Nithin Dabilpuram <ndabilpuram@marvell.com>
drivers/common/cnxk/meson.build
drivers/common/cnxk/roc_tim.c
drivers/common/cnxk/roc_tim_irq.c [new file with mode: 0644]
drivers/common/cnxk/roc_tim_priv.h

index 1b02178..4573d13 100644 (file)
@@ -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')
index 37faa37..387164b 100644 (file)
@@ -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 (file)
index 0000000..7bd3e76
--- /dev/null
@@ -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);
+}
index 08697f6..cc083d2 100644 (file)
@@ -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_ */