#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)
{
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;
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;
}
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;
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;
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;
}
--- /dev/null
+/* 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);
+}