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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+5 −0
Original line number Diff line number Diff line
@@ -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;
}

+4 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
// 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);
}
+72 −0
Original line number Diff line number Diff line
@@ -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 */