Commit aba53d5d authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller

octeontx2-af: NIX block admin queue init

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: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 57856dde
...@@ -7,4 +7,4 @@ obj-$(CONFIG_OCTEONTX2_MBOX) += octeontx2_mbox.o ...@@ -7,4 +7,4 @@ obj-$(CONFIG_OCTEONTX2_MBOX) += octeontx2_mbox.o
obj-$(CONFIG_OCTEONTX2_AF) += octeontx2_af.o obj-$(CONFIG_OCTEONTX2_AF) += octeontx2_af.o
octeontx2_mbox-y := mbox.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
...@@ -566,6 +566,7 @@ static void rvu_free_hw_resources(struct rvu *rvu) ...@@ -566,6 +566,7 @@ static void rvu_free_hw_resources(struct rvu *rvu)
u64 cfg; u64 cfg;
rvu_npa_freemem(rvu); rvu_npa_freemem(rvu);
rvu_nix_freemem(rvu);
/* Free block LF bitmaps */ /* Free block LF bitmaps */
for (id = 0; id < BLK_COUNT; id++) { for (id = 0; id < BLK_COUNT; id++) {
...@@ -774,6 +775,10 @@ static int rvu_setup_hw_resources(struct rvu *rvu) ...@@ -774,6 +775,10 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
if (err) if (err)
return err; return err;
err = rvu_nix_init(rvu);
if (err)
return err;
return 0; return 0;
} }
......
...@@ -226,4 +226,8 @@ int rvu_mbox_handler_NPA_LF_ALLOC(struct rvu *rvu, ...@@ -226,4 +226,8 @@ int rvu_mbox_handler_NPA_LF_ALLOC(struct rvu *rvu,
struct npa_lf_alloc_rsp *rsp); struct npa_lf_alloc_rsp *rsp);
int rvu_mbox_handler_NPA_LF_FREE(struct rvu *rvu, struct msg_req *req, int rvu_mbox_handler_NPA_LF_FREE(struct rvu *rvu, struct msg_req *req,
struct msg_rsp *rsp); struct msg_rsp *rsp);
/* NIX APIs */
int rvu_nix_init(struct rvu *rvu);
void rvu_nix_freemem(struct rvu *rvu);
#endif /* RVU_H */ #endif /* RVU_H */
// 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);
}
...@@ -354,4 +354,76 @@ struct npa_pool_s { ...@@ -354,4 +354,76 @@ struct npa_pool_s {
u64 reserved_896_959; /* W14 */ u64 reserved_896_959; /* W14 */
u64 reserved_960_1023; /* W15 */ 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 */ #endif /* RVU_STRUCT_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment