octeontx2-af: NPA AQ instruction enqueue support
authorSunil Goutham <sgoutham@marvell.com>
Tue, 16 Oct 2018 11:27:13 +0000 (16:57 +0530)
committerDavid S. Miller <davem@davemloft.net>
Thu, 18 Oct 2018 04:33:42 +0000 (21:33 -0700)
Add support for a RVU PF/VF to submit instructions to NPA AQ
via mbox. Instructions can be to init/write/read Aura/Pool/Qint
contexts. In case of read, context will be returned as part of
response to the mbox msg received.

Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/common.h
drivers/net/ethernet/marvell/octeontx2/af/mbox.h
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_npa.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_struct.h

index c64d241..24021cb 100644 (file)
@@ -118,4 +118,17 @@ enum npa_aura_sz {
 
 #define NPA_AURA_COUNT(x)      (1ULL << ((x) + 6))
 
+/* NPA AQ result structure for init/read/write of aura HW contexts */
+struct npa_aq_aura_res {
+       struct  npa_aq_res_s    res;
+       struct  npa_aura_s      aura_ctx;
+       struct  npa_aura_s      ctx_mask;
+};
+
+/* NPA AQ result structure for init/read/write of pool HW contexts */
+struct npa_aq_pool_res {
+       struct  npa_aq_res_s    res;
+       struct  npa_pool_s      pool_ctx;
+       struct  npa_pool_s      ctx_mask;
+};
 #endif /* COMMON_H */
index 8135339..bf11058 100644 (file)
@@ -141,6 +141,7 @@ M(CGX_INTLBK_DISABLE,       0x20B, msg_req, msg_rsp)                        \
 /* NPA mbox IDs (range 0x400 - 0x5FF) */                               \
 M(NPA_LF_ALLOC,                0x400, npa_lf_alloc_req, npa_lf_alloc_rsp)      \
 M(NPA_LF_FREE,         0x401, msg_req, msg_rsp)                        \
+M(NPA_AQ_ENQ,          0x402, npa_aq_enq_req, npa_aq_enq_rsp)          \
 /* SSO/SSOW mbox IDs (range 0x600 - 0x7FF) */                          \
 /* TIM mbox IDs (range 0x800 - 0x9FF) */                               \
 /* CPT mbox IDs (range 0xA00 - 0xBFF) */                               \
@@ -290,4 +291,38 @@ struct npa_lf_alloc_rsp {
        u16 qints; /* NPA_AF_CONST::QINTS */
 };
 
+/* NPA AQ enqueue msg */
+struct npa_aq_enq_req {
+       struct mbox_msghdr hdr;
+       u32 aura_id;
+       u8 ctype;
+       u8 op;
+       union {
+               /* Valid when op == WRITE/INIT and ctype == AURA.
+                * LF fills the pool_id in aura.pool_addr. AF will translate
+                * the pool_id to pool context pointer.
+                */
+               struct npa_aura_s aura;
+               /* Valid when op == WRITE/INIT and ctype == POOL */
+               struct npa_pool_s pool;
+       };
+       /* Mask data when op == WRITE (1=write, 0=don't write) */
+       union {
+               /* Valid when op == WRITE and ctype == AURA */
+               struct npa_aura_s aura_mask;
+               /* Valid when op == WRITE and ctype == POOL */
+               struct npa_pool_s pool_mask;
+       };
+};
+
+struct npa_aq_enq_rsp {
+       struct mbox_msghdr hdr;
+       union {
+               /* Valid when op == READ and ctype == AURA */
+               struct npa_aura_s aura;
+               /* Valid when op == READ and ctype == POOL */
+               struct npa_pool_s pool;
+       };
+};
+
 #endif /* MBOX_H */
index b32d1f1..a70c26b 100644 (file)
@@ -213,6 +213,9 @@ int rvu_mbox_handler_CGX_INTLBK_DISABLE(struct rvu *rvu, struct msg_req *req,
 /* NPA APIs */
 int rvu_npa_init(struct rvu *rvu);
 void rvu_npa_freemem(struct rvu *rvu);
+int rvu_mbox_handler_NPA_AQ_ENQ(struct rvu *rvu,
+                               struct npa_aq_enq_req *req,
+                               struct npa_aq_enq_rsp *rsp);
 int rvu_mbox_handler_NPA_LF_ALLOC(struct rvu *rvu,
                                  struct npa_lf_alloc_req *req,
                                  struct npa_lf_alloc_rsp *rsp);
index ea0c5e0..4ff0e76 100644 (file)
 #include "rvu_reg.h"
 #include "rvu.h"
 
+static int npa_aq_enqueue_wait(struct rvu *rvu, struct rvu_block *block,
+                              struct npa_aq_inst_s *inst)
+{
+       struct admin_queue *aq = block->aq;
+       struct npa_aq_res_s *result;
+       int timeout = 1000;
+       u64 reg, head;
+
+       result = (struct npa_aq_res_s *)aq->res->base;
+
+       /* Get current head pointer where to append this instruction */
+       reg = rvu_read64(rvu, block->addr, NPA_AF_AQ_STATUS);
+       head = (reg >> 4) & AQ_PTR_MASK;
+
+       memcpy((void *)(aq->inst->base + (head * aq->inst->entry_sz)),
+              (void *)inst, aq->inst->entry_sz);
+       memset(result, 0, sizeof(*result));
+       /* sync into memory */
+       wmb();
+
+       /* Ring the doorbell and wait for result */
+       rvu_write64(rvu, block->addr, NPA_AF_AQ_DOOR, 1);
+       while (result->compcode == NPA_AQ_COMP_NOTDONE) {
+               cpu_relax();
+               udelay(1);
+               timeout--;
+               if (!timeout)
+                       return -EBUSY;
+       }
+
+       if (result->compcode != NPA_AQ_COMP_GOOD)
+               /* TODO: Replace this with some error code */
+               return -EBUSY;
+
+       return 0;
+}
+
+static int rvu_npa_aq_enq_inst(struct rvu *rvu, struct npa_aq_enq_req *req,
+                              struct npa_aq_enq_rsp *rsp)
+{
+       struct rvu_hwinfo *hw = rvu->hw;
+       u16 pcifunc = req->hdr.pcifunc;
+       int blkaddr, npalf, rc = 0;
+       struct npa_aq_inst_s inst;
+       struct rvu_block *block;
+       struct admin_queue *aq;
+       struct rvu_pfvf *pfvf;
+       void *ctx, *mask;
+
+       pfvf = rvu_get_pfvf(rvu, pcifunc);
+       if (!pfvf->aura_ctx || req->aura_id >= pfvf->aura_ctx->qsize)
+               return NPA_AF_ERR_AQ_ENQUEUE;
+
+       blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPA, pcifunc);
+       if (!pfvf->npalf || blkaddr < 0)
+               return NPA_AF_ERR_AF_LF_INVALID;
+
+       block = &hw->block[blkaddr];
+       aq = block->aq;
+       if (!aq) {
+               dev_warn(rvu->dev, "%s: NPA AQ not initialized\n", __func__);
+               return NPA_AF_ERR_AQ_ENQUEUE;
+       }
+
+       npalf = rvu_get_lf(rvu, block, pcifunc, 0);
+       if (npalf < 0)
+               return NPA_AF_ERR_AF_LF_INVALID;
+
+       memset(&inst, 0, sizeof(struct npa_aq_inst_s));
+       inst.cindex = req->aura_id;
+       inst.lf = npalf;
+       inst.ctype = req->ctype;
+       inst.op = req->op;
+       /* Currently we are not supporting enqueuing multiple instructions,
+        * so always choose first entry in result memory.
+        */
+       inst.res_addr = (u64)aq->res->iova;
+
+       /* Clean result + context memory */
+       memset(aq->res->base, 0, aq->res->entry_sz);
+       /* Context needs to be written at RES_ADDR + 128 */
+       ctx = aq->res->base + 128;
+       /* Mask needs to be written at RES_ADDR + 256 */
+       mask = aq->res->base + 256;
+
+       switch (req->op) {
+       case NPA_AQ_INSTOP_WRITE:
+               /* Copy context and write mask */
+               if (req->ctype == NPA_AQ_CTYPE_AURA) {
+                       memcpy(mask, &req->aura_mask,
+                              sizeof(struct npa_aura_s));
+                       memcpy(ctx, &req->aura, sizeof(struct npa_aura_s));
+               } else {
+                       memcpy(mask, &req->pool_mask,
+                              sizeof(struct npa_pool_s));
+                       memcpy(ctx, &req->pool, sizeof(struct npa_pool_s));
+               }
+               break;
+       case NPA_AQ_INSTOP_INIT:
+               if (req->ctype == NPA_AQ_CTYPE_AURA) {
+                       if (req->aura.pool_addr >= pfvf->pool_ctx->qsize) {
+                               rc = NPA_AF_ERR_AQ_FULL;
+                               break;
+                       }
+                       /* Set pool's context address */
+                       req->aura.pool_addr = pfvf->pool_ctx->iova +
+                       (req->aura.pool_addr * pfvf->pool_ctx->entry_sz);
+                       memcpy(ctx, &req->aura, sizeof(struct npa_aura_s));
+               } else { /* POOL's context */
+                       memcpy(ctx, &req->pool, sizeof(struct npa_pool_s));
+               }
+               break;
+       case NPA_AQ_INSTOP_NOP:
+       case NPA_AQ_INSTOP_READ:
+       case NPA_AQ_INSTOP_LOCK:
+       case NPA_AQ_INSTOP_UNLOCK:
+               break;
+       default:
+               rc = NPA_AF_ERR_AQ_FULL;
+               break;
+       }
+
+       if (rc)
+               return rc;
+
+       spin_lock(&aq->lock);
+
+       /* Submit the instruction to AQ */
+       rc = npa_aq_enqueue_wait(rvu, block, &inst);
+       if (rc) {
+               spin_unlock(&aq->lock);
+               return rc;
+       }
+
+       spin_unlock(&aq->lock);
+
+       if (rsp) {
+               /* Copy read context into mailbox */
+               if (req->op == NPA_AQ_INSTOP_READ) {
+                       if (req->ctype == NPA_AQ_CTYPE_AURA)
+                               memcpy(&rsp->aura, ctx,
+                                      sizeof(struct npa_aura_s));
+                       else
+                               memcpy(&rsp->pool, ctx,
+                                      sizeof(struct npa_pool_s));
+               }
+       }
+
+       return 0;
+}
+
+int rvu_mbox_handler_NPA_AQ_ENQ(struct rvu *rvu,
+                               struct npa_aq_enq_req *req,
+                               struct npa_aq_enq_rsp *rsp)
+{
+       return rvu_npa_aq_enq_inst(rvu, req, rsp);
+}
+
 static void npa_ctx_free(struct rvu *rvu, struct rvu_pfvf *pfvf)
 {
        qmem_free(rvu->dev, pfvf->aura_ctx);
index ae1c18d..6ebe1c9 100644 (file)
@@ -136,4 +136,222 @@ struct npa_aq_res_s {
 #endif
        u64 reserved_64_127;            /* W1 */
 };
+
+struct npa_aura_s {
+       u64 pool_addr;                  /* W0 */
+#if defined(__BIG_ENDIAN_BITFIELD)     /* W1 */
+       u64 avg_level             : 8;
+       u64 reserved_118_119      : 2;
+       u64 shift                 : 6;
+       u64 aura_drop             : 8;
+       u64 reserved_98_103       : 6;
+       u64 bp_ena                : 2;
+       u64 aura_drop_ena         : 1;
+       u64 pool_drop_ena         : 1;
+       u64 reserved_93           : 1;
+       u64 avg_con               : 9;
+       u64 pool_way_mask         : 16;
+       u64 pool_caching          : 1;
+       u64 reserved_65           : 2;
+       u64 ena                   : 1;
+#else
+       u64 ena                   : 1;
+       u64 reserved_65           : 2;
+       u64 pool_caching          : 1;
+       u64 pool_way_mask         : 16;
+       u64 avg_con               : 9;
+       u64 reserved_93           : 1;
+       u64 pool_drop_ena         : 1;
+       u64 aura_drop_ena         : 1;
+       u64 bp_ena                : 2;
+       u64 reserved_98_103       : 6;
+       u64 aura_drop             : 8;
+       u64 shift                 : 6;
+       u64 reserved_118_119      : 2;
+       u64 avg_level             : 8;
+#endif
+#if defined(__BIG_ENDIAN_BITFIELD)     /* W2 */
+       u64 reserved_189_191      : 3;
+       u64 nix1_bpid             : 9;
+       u64 reserved_177_179      : 3;
+       u64 nix0_bpid             : 9;
+       u64 reserved_164_167      : 4;
+       u64 count                 : 36;
+#else
+       u64 count                 : 36;
+       u64 reserved_164_167      : 4;
+       u64 nix0_bpid             : 9;
+       u64 reserved_177_179      : 3;
+       u64 nix1_bpid             : 9;
+       u64 reserved_189_191      : 3;
+#endif
+#if defined(__BIG_ENDIAN_BITFIELD)     /* W3 */
+       u64 reserved_252_255      : 4;
+       u64 fc_hyst_bits          : 4;
+       u64 fc_stype              : 2;
+       u64 fc_up_crossing        : 1;
+       u64 fc_ena                : 1;
+       u64 reserved_240_243      : 4;
+       u64 bp                    : 8;
+       u64 reserved_228_231      : 4;
+       u64 limit                 : 36;
+#else
+       u64 limit                 : 36;
+       u64 reserved_228_231      : 4;
+       u64 bp                    : 8;
+       u64 reserved_240_243      : 4;
+       u64 fc_ena                : 1;
+       u64 fc_up_crossing        : 1;
+       u64 fc_stype              : 2;
+       u64 fc_hyst_bits          : 4;
+       u64 reserved_252_255      : 4;
+#endif
+       u64 fc_addr;                    /* W4 */
+#if defined(__BIG_ENDIAN_BITFIELD)     /* W5 */
+       u64 reserved_379_383      : 5;
+       u64 err_qint_idx          : 7;
+       u64 reserved_371          : 1;
+       u64 thresh_qint_idx       : 7;
+       u64 reserved_363          : 1;
+       u64 thresh_up             : 1;
+       u64 thresh_int_ena        : 1;
+       u64 thresh_int            : 1;
+       u64 err_int_ena           : 8;
+       u64 err_int               : 8;
+       u64 update_time           : 16;
+       u64 pool_drop             : 8;
+#else
+       u64 pool_drop             : 8;
+       u64 update_time           : 16;
+       u64 err_int               : 8;
+       u64 err_int_ena           : 8;
+       u64 thresh_int            : 1;
+       u64 thresh_int_ena        : 1;
+       u64 thresh_up             : 1;
+       u64 reserved_363          : 1;
+       u64 thresh_qint_idx       : 7;
+       u64 reserved_371          : 1;
+       u64 err_qint_idx          : 7;
+       u64 reserved_379_383      : 5;
+#endif
+#if defined(__BIG_ENDIAN_BITFIELD)     /* W6 */
+       u64 reserved_420_447      : 28;
+       u64 thresh                : 36;
+#else
+       u64 thresh                : 36;
+       u64 reserved_420_447      : 28;
+#endif
+       u64 reserved_448_511;           /* W7 */
+};
+
+struct npa_pool_s {
+       u64 stack_base;                 /* W0 */
+#if defined(__BIG_ENDIAN_BITFIELD)     /* W1 */
+       u64 reserved_115_127      : 13;
+       u64 buf_size              : 11;
+       u64 reserved_100_103      : 4;
+       u64 buf_offset            : 12;
+       u64 stack_way_mask        : 16;
+       u64 reserved_70_71        : 3;
+       u64 stack_caching         : 1;
+       u64 reserved_66_67        : 2;
+       u64 nat_align             : 1;
+       u64 ena                   : 1;
+#else
+       u64 ena                   : 1;
+       u64 nat_align             : 1;
+       u64 reserved_66_67        : 2;
+       u64 stack_caching         : 1;
+       u64 reserved_70_71        : 3;
+       u64 stack_way_mask        : 16;
+       u64 buf_offset            : 12;
+       u64 reserved_100_103      : 4;
+       u64 buf_size              : 11;
+       u64 reserved_115_127      : 13;
+#endif
+#if defined(__BIG_ENDIAN_BITFIELD)     /* W2 */
+       u64 stack_pages           : 32;
+       u64 stack_max_pages       : 32;
+#else
+       u64 stack_max_pages       : 32;
+       u64 stack_pages           : 32;
+#endif
+#if defined(__BIG_ENDIAN_BITFIELD)     /* W3 */
+       u64 reserved_240_255      : 16;
+       u64 op_pc                 : 48;
+#else
+       u64 op_pc                 : 48;
+       u64 reserved_240_255      : 16;
+#endif
+#if defined(__BIG_ENDIAN_BITFIELD)     /* W4 */
+       u64 reserved_316_319      : 4;
+       u64 update_time           : 16;
+       u64 reserved_297_299      : 3;
+       u64 fc_up_crossing        : 1;
+       u64 fc_hyst_bits          : 4;
+       u64 fc_stype              : 2;
+       u64 fc_ena                : 1;
+       u64 avg_con               : 9;
+       u64 avg_level             : 8;
+       u64 reserved_270_271      : 2;
+       u64 shift                 : 6;
+       u64 reserved_260_263      : 4;
+       u64 stack_offset          : 4;
+#else
+       u64 stack_offset          : 4;
+       u64 reserved_260_263      : 4;
+       u64 shift                 : 6;
+       u64 reserved_270_271      : 2;
+       u64 avg_level             : 8;
+       u64 avg_con               : 9;
+       u64 fc_ena                : 1;
+       u64 fc_stype              : 2;
+       u64 fc_hyst_bits          : 4;
+       u64 fc_up_crossing        : 1;
+       u64 reserved_297_299      : 3;
+       u64 update_time           : 16;
+       u64 reserved_316_319      : 4;
+#endif
+       u64 fc_addr;                    /* W5 */
+       u64 ptr_start;                  /* W6 */
+       u64 ptr_end;                    /* W7 */
+#if defined(__BIG_ENDIAN_BITFIELD)     /* W8 */
+       u64 reserved_571_575      : 5;
+       u64 err_qint_idx          : 7;
+       u64 reserved_563          : 1;
+       u64 thresh_qint_idx       : 7;
+       u64 reserved_555          : 1;
+       u64 thresh_up             : 1;
+       u64 thresh_int_ena        : 1;
+       u64 thresh_int            : 1;
+       u64 err_int_ena           : 8;
+       u64 err_int               : 8;
+       u64 reserved_512_535      : 24;
+#else
+       u64 reserved_512_535      : 24;
+       u64 err_int               : 8;
+       u64 err_int_ena           : 8;
+       u64 thresh_int            : 1;
+       u64 thresh_int_ena        : 1;
+       u64 thresh_up             : 1;
+       u64 reserved_555          : 1;
+       u64 thresh_qint_idx       : 7;
+       u64 reserved_563          : 1;
+       u64 err_qint_idx          : 7;
+       u64 reserved_571_575      : 5;
+#endif
+#if defined(__BIG_ENDIAN_BITFIELD)     /* W9 */
+       u64 reserved_612_639      : 28;
+       u64 thresh                : 36;
+#else
+       u64 thresh                : 36;
+       u64 reserved_612_639      : 28;
+#endif
+       u64 reserved_640_703;           /* W10 */
+       u64 reserved_704_767;           /* W11 */
+       u64 reserved_768_831;           /* W12 */
+       u64 reserved_832_895;           /* W13 */
+       u64 reserved_896_959;           /* W14 */
+       u64 reserved_960_1023;          /* W15 */
+};
 #endif /* RVU_STRUCT_H */