octeontx2-af: NIX block admin queue init
authorSunil Goutham <sgoutham@marvell.com>
Tue, 16 Oct 2018 11:27:15 +0000 (16:57 +0530)
committerDavid S. Miller <davem@davemloft.net>
Thu, 18 Oct 2018 04:33:43 +0000 (21:33 -0700)
Initialize NIX admin queue (AQ) i.e alloc memory for
AQ instructions and for the results. All NIX LFs will submit
instructions to AQ to init/write/read RQ/SQ/CQ/RSS contexts
and in case of read, get context from result memory.

Also before configuring/using NIX block calibrate X2P bus
and check if NIX interfaces like CGX and LBK are in active
and working state.

Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/Makefile
drivers/net/ethernet/marvell/octeontx2/af/rvu.c
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c [new file with mode: 0644]
drivers/net/ethernet/marvell/octeontx2/af/rvu_struct.h

index bdb4f98572a0e452a9033f196247c3c22a4da1f9..45b108f8f95517b897c26889b5f19953c81a1710 100644 (file)
@@ -7,4 +7,4 @@ obj-$(CONFIG_OCTEONTX2_MBOX) += octeontx2_mbox.o
 obj-$(CONFIG_OCTEONTX2_AF) += octeontx2_af.o
 
 octeontx2_mbox-y := mbox.o
-octeontx2_af-y := cgx.o rvu.o rvu_cgx.o rvu_npa.o
+octeontx2_af-y := cgx.o rvu.o rvu_cgx.o rvu_npa.o rvu_nix.o
index 5d4917c41d510253f8b2f4124978917d4b5ce990..c06cca9c9e1a539acc8ebb1053e562dddbd845a7 100644 (file)
@@ -566,6 +566,7 @@ static void rvu_free_hw_resources(struct rvu *rvu)
        u64 cfg;
 
        rvu_npa_freemem(rvu);
+       rvu_nix_freemem(rvu);
 
        /* Free block LF bitmaps */
        for (id = 0; id < BLK_COUNT; id++) {
@@ -774,6 +775,10 @@ init:
        if (err)
                return err;
 
+       err = rvu_nix_init(rvu);
+       if (err)
+               return err;
+
        return 0;
 }
 
index bfc95c3ebe977f296a070fbae2f71c08aaf76c1c..0d0fb1d1dcd958a83977e76857f21f3de7095426 100644 (file)
@@ -226,4 +226,8 @@ int rvu_mbox_handler_NPA_LF_ALLOC(struct rvu *rvu,
                                  struct npa_lf_alloc_rsp *rsp);
 int rvu_mbox_handler_NPA_LF_FREE(struct rvu *rvu, struct msg_req *req,
                                 struct msg_rsp *rsp);
+
+/* NIX APIs */
+int rvu_nix_init(struct rvu *rvu);
+void rvu_nix_freemem(struct rvu *rvu);
 #endif /* RVU_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
new file mode 100644 (file)
index 0000000..5ff9e6b
--- /dev/null
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell OcteonTx2 RVU Admin Function driver
+ *
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "rvu_struct.h"
+#include "rvu_reg.h"
+#include "rvu.h"
+#include "cgx.h"
+
+static int nix_calibrate_x2p(struct rvu *rvu, int blkaddr)
+{
+       int idx, err;
+       u64 status;
+
+       /* Start X2P bus calibration */
+       rvu_write64(rvu, blkaddr, NIX_AF_CFG,
+                   rvu_read64(rvu, blkaddr, NIX_AF_CFG) | BIT_ULL(9));
+       /* Wait for calibration to complete */
+       err = rvu_poll_reg(rvu, blkaddr,
+                          NIX_AF_STATUS, BIT_ULL(10), false);
+       if (err) {
+               dev_err(rvu->dev, "NIX X2P bus calibration failed\n");
+               return err;
+       }
+
+       status = rvu_read64(rvu, blkaddr, NIX_AF_STATUS);
+       /* Check if CGX devices are ready */
+       for (idx = 0; idx < cgx_get_cgx_cnt(); idx++) {
+               if (status & (BIT_ULL(16 + idx)))
+                       continue;
+               dev_err(rvu->dev,
+                       "CGX%d didn't respond to NIX X2P calibration\n", idx);
+               err = -EBUSY;
+       }
+
+       /* Check if LBK is ready */
+       if (!(status & BIT_ULL(19))) {
+               dev_err(rvu->dev,
+                       "LBK didn't respond to NIX X2P calibration\n");
+               err = -EBUSY;
+       }
+
+       /* Clear 'calibrate_x2p' bit */
+       rvu_write64(rvu, blkaddr, NIX_AF_CFG,
+                   rvu_read64(rvu, blkaddr, NIX_AF_CFG) & ~BIT_ULL(9));
+       if (err || (status & 0x3FFULL))
+               dev_err(rvu->dev,
+                       "NIX X2P calibration failed, status 0x%llx\n", status);
+       if (err)
+               return err;
+       return 0;
+}
+
+static int nix_aq_init(struct rvu *rvu, struct rvu_block *block)
+{
+       u64 cfg;
+       int err;
+
+       /* Set admin queue endianness */
+       cfg = rvu_read64(rvu, block->addr, NIX_AF_CFG);
+#ifdef __BIG_ENDIAN
+       cfg |= BIT_ULL(1);
+       rvu_write64(rvu, block->addr, NIX_AF_CFG, cfg);
+#else
+       cfg &= ~BIT_ULL(1);
+       rvu_write64(rvu, block->addr, NIX_AF_CFG, cfg);
+#endif
+
+       /* Do not bypass NDC cache */
+       cfg = rvu_read64(rvu, block->addr, NIX_AF_NDC_CFG);
+       cfg &= ~0x3FFEULL;
+       rvu_write64(rvu, block->addr, NIX_AF_NDC_CFG, cfg);
+
+       /* Result structure can be followed by RQ/SQ/CQ context at
+        * RES + 128bytes and a write mask at RES + 256 bytes, depending on
+        * operation type. Alloc sufficient result memory for all operations.
+        */
+       err = rvu_aq_alloc(rvu, &block->aq,
+                          Q_COUNT(AQ_SIZE), sizeof(struct nix_aq_inst_s),
+                          ALIGN(sizeof(struct nix_aq_res_s), 128) + 256);
+       if (err)
+               return err;
+
+       rvu_write64(rvu, block->addr, NIX_AF_AQ_CFG, AQ_SIZE);
+       rvu_write64(rvu, block->addr,
+                   NIX_AF_AQ_BASE, (u64)block->aq->inst->iova);
+       return 0;
+}
+
+int rvu_nix_init(struct rvu *rvu)
+{
+       struct rvu_hwinfo *hw = rvu->hw;
+       struct rvu_block *block;
+       int blkaddr, err;
+
+       blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
+       if (blkaddr < 0)
+               return 0;
+       block = &hw->block[blkaddr];
+
+       /* Calibrate X2P bus to check if CGX/LBK links are fine */
+       err = nix_calibrate_x2p(rvu, blkaddr);
+       if (err)
+               return err;
+
+       /* Initialize admin queue */
+       err = nix_aq_init(rvu, block);
+       if (err)
+               return err;
+
+       /* Restore CINT timer delay to HW reset values */
+       rvu_write64(rvu, blkaddr, NIX_AF_CINT_DELAY, 0x0ULL);
+
+       return 0;
+}
+
+void rvu_nix_freemem(struct rvu *rvu)
+{
+       struct rvu_hwinfo *hw = rvu->hw;
+       struct rvu_block *block;
+       int blkaddr;
+
+       blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, 0);
+       if (blkaddr < 0)
+               return;
+
+       block = &hw->block[blkaddr];
+       rvu_aq_free(rvu, block->aq);
+}
index 6ebe1c95ea0fbb9eb7c9ef4ee4dbd8b6518403a1..0981f67d6175cf88dbbefff15833a6a0003213d1 100644 (file)
@@ -354,4 +354,76 @@ struct npa_pool_s {
        u64 reserved_896_959;           /* W14 */
        u64 reserved_960_1023;          /* W15 */
 };
+
+/* NIX admin queue completion status */
+enum nix_aq_comp {
+       NIX_AQ_COMP_NOTDONE        = 0x0,
+       NIX_AQ_COMP_GOOD           = 0x1,
+       NIX_AQ_COMP_SWERR          = 0x2,
+       NIX_AQ_COMP_CTX_POISON     = 0x3,
+       NIX_AQ_COMP_CTX_FAULT      = 0x4,
+       NIX_AQ_COMP_LOCKERR        = 0x5,
+       NIX_AQ_COMP_SQB_ALLOC_FAIL = 0x6,
+};
+
+/* NIX admin queue context types */
+enum nix_aq_ctype {
+       NIX_AQ_CTYPE_RQ   = 0x0,
+       NIX_AQ_CTYPE_SQ   = 0x1,
+       NIX_AQ_CTYPE_CQ   = 0x2,
+       NIX_AQ_CTYPE_MCE  = 0x3,
+       NIX_AQ_CTYPE_RSS  = 0x4,
+       NIX_AQ_CTYPE_DYNO = 0x5,
+};
+
+/* NIX admin queue instruction opcodes */
+enum nix_aq_instop {
+       NIX_AQ_INSTOP_NOP    = 0x0,
+       NIX_AQ_INSTOP_INIT   = 0x1,
+       NIX_AQ_INSTOP_WRITE  = 0x2,
+       NIX_AQ_INSTOP_READ   = 0x3,
+       NIX_AQ_INSTOP_LOCK   = 0x4,
+       NIX_AQ_INSTOP_UNLOCK = 0x5,
+};
+
+/* NIX admin queue instruction structure */
+struct nix_aq_inst_s {
+#if defined(__BIG_ENDIAN_BITFIELD)
+       u64 doneint             : 1;    /* W0 */
+       u64 reserved_44_62      : 19;
+       u64 cindex              : 20;
+       u64 reserved_15_23      : 9;
+       u64 lf                  : 7;
+       u64 ctype               : 4;
+       u64 op                  : 4;
+#else
+       u64 op                  : 4;
+       u64 ctype               : 4;
+       u64 lf                  : 7;
+       u64 reserved_15_23      : 9;
+       u64 cindex              : 20;
+       u64 reserved_44_62      : 19;
+       u64 doneint             : 1;
+#endif
+       u64 res_addr;                   /* W1 */
+};
+
+/* NIX admin queue result structure */
+struct nix_aq_res_s {
+#if defined(__BIG_ENDIAN_BITFIELD)
+       u64 reserved_17_63      : 47;   /* W0 */
+       u64 doneint             : 1;
+       u64 compcode            : 8;
+       u64 ctype               : 4;
+       u64 op                  : 4;
+#else
+       u64 op                  : 4;
+       u64 ctype               : 4;
+       u64 compcode            : 8;
+       u64 doneint             : 1;
+       u64 reserved_17_63      : 47;
+#endif
+       u64 reserved_64_127;            /* W1 */
+};
+
 #endif /* RVU_STRUCT_H */