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: Sunil Goutham <sgoutham@marvell.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
57856dde11
commit
aba53d5dbc
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
138
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
Normal file
138
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
Normal file
@ -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);
|
||||
}
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user