Commit e6a16043 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'octeopntx2-LMTST-regions'



Geetha sowjanya says:

====================
Dynamic LMTST region setup

This patch series allows RVU PF/VF to allocate memory for
LMTST operations instead of using memory reserved by firmware
which is mapped as device memory.
The LMTST mapping table contains the RVU PF/VF LMTST memory base
address entries. This table is used by hardware for LMTST operations.
Patch1 introduces new mailbox message to update the LMTST table with
the new allocated memory address.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents dbe69e43 5c051207
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -134,6 +134,8 @@ M(MSIX_OFFSET, 0x005, msix_offset, msg_req, msix_offset_rsp) \
M(VF_FLR,		0x006, vf_flr, msg_req, msg_rsp)		\
M(PTP_OP,		0x007, ptp_op, ptp_req, ptp_rsp)		\
M(GET_HW_CAP,		0x008, get_hw_cap, msg_req, get_hw_cap_rsp)	\
M(LMTST_TBL_SETUP,	0x00a, lmtst_tbl_setup, lmtst_tbl_setup_req,    \
				msg_rsp)				\
M(SET_VF_PERM,		0x00b, set_vf_perm, set_vf_perm, msg_rsp)	\
/* CGX mbox IDs (range 0x200 - 0x3FF) */				\
M(CGX_START_RXTX,	0x200, cgx_start_rxtx, msg_req, msg_rsp)	\
@@ -1278,6 +1280,14 @@ struct set_vf_perm {
	u64	flags;
};

struct lmtst_tbl_setup_req {
	struct mbox_msghdr hdr;
	u16 base_pcifunc;
	u8  use_local_lmt_region;
	u64 lmt_iova;
	u64 rsvd[4];
};

/* CPT mailbox error codes
 * Range 901 - 1000.
 */
+1 −0
Original line number Diff line number Diff line
@@ -2333,6 +2333,7 @@ static void __rvu_flr_handler(struct rvu *rvu, u16 pcifunc)
	rvu_blklf_teardown(rvu, pcifunc, BLKADDR_SSOW);
	rvu_blklf_teardown(rvu, pcifunc, BLKADDR_SSO);
	rvu_blklf_teardown(rvu, pcifunc, BLKADDR_NPA);
	rvu_reset_lmt_map_tbl(rvu, pcifunc);
	rvu_detach_rsrcs(rvu, NULL, pcifunc);
	mutex_unlock(&rvu->flr_lock);
}
+4 −0
Original line number Diff line number Diff line
@@ -243,6 +243,7 @@ struct rvu_pfvf {
	u8	nix_blkaddr; /* BLKADDR_NIX0/1 assigned to this PF */
	u8	nix_rx_intf; /* NIX0_RX/NIX1_RX interface to NPC */
	u8	nix_tx_intf; /* NIX0_TX/NIX1_TX interface to NPC */
	u64     lmt_base_addr; /* Preseving the pcifunc's lmtst base addr*/
	unsigned long flags;
};

@@ -754,6 +755,9 @@ int rvu_cpt_lf_teardown(struct rvu *rvu, u16 pcifunc, int lf, int slot);
int rvu_set_channels_base(struct rvu *rvu);
void rvu_program_channels(struct rvu *rvu);

/* CN10K RVU - LMT*/
void rvu_reset_lmt_map_tbl(struct rvu *rvu, u16 pcifunc);

#ifdef CONFIG_DEBUG_FS
void rvu_dbg_init(struct rvu *rvu);
void rvu_dbg_exit(struct rvu *rvu);
+200 −0
Original line number Diff line number Diff line
@@ -10,6 +10,206 @@
#include "cgx.h"
#include "rvu_reg.h"

/* RVU LMTST */
#define LMT_TBL_OP_READ		0
#define LMT_TBL_OP_WRITE	1
#define LMT_MAP_TABLE_SIZE	(128 * 1024)
#define LMT_MAPTBL_ENTRY_SIZE	16

/* Function to perform operations (read/write) on lmtst map table */
static int lmtst_map_table_ops(struct rvu *rvu, u32 index, u64 *val,
			       int lmt_tbl_op)
{
	void __iomem *lmt_map_base;
	u64 tbl_base;

	tbl_base = rvu_read64(rvu, BLKADDR_APR, APR_AF_LMT_MAP_BASE);

	lmt_map_base = ioremap_wc(tbl_base, LMT_MAP_TABLE_SIZE);
	if (!lmt_map_base) {
		dev_err(rvu->dev, "Failed to setup lmt map table mapping!!\n");
		return -ENOMEM;
	}

	if (lmt_tbl_op == LMT_TBL_OP_READ) {
		*val = readq(lmt_map_base + index);
	} else {
		writeq((*val), (lmt_map_base + index));
		/* Flushing the AP interceptor cache to make APR_LMT_MAP_ENTRY_S
		 * changes effective. Write 1 for flush and read is being used as a
		 * barrier and sets up a data dependency. Write to 0 after a write
		 * to 1 to complete the flush.
		 */
		rvu_write64(rvu, BLKADDR_APR, APR_AF_LMT_CTL, BIT_ULL(0));
		rvu_read64(rvu, BLKADDR_APR, APR_AF_LMT_CTL);
		rvu_write64(rvu, BLKADDR_APR, APR_AF_LMT_CTL, 0x00);
	}

	iounmap(lmt_map_base);
	return 0;
}

static u32 rvu_get_lmtst_tbl_index(struct rvu *rvu, u16 pcifunc)
{
	return ((rvu_get_pf(pcifunc) * rvu->hw->total_vfs) +
		(pcifunc & RVU_PFVF_FUNC_MASK)) * LMT_MAPTBL_ENTRY_SIZE;
}

static int rvu_get_lmtaddr(struct rvu *rvu, u16 pcifunc,
			   u64 iova, u64 *lmt_addr)
{
	u64 pa, val, pf;
	int err;

	if (!iova) {
		dev_err(rvu->dev, "%s Requested Null address for transulation\n", __func__);
		return -EINVAL;
	}

	rvu_write64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_ADDR_REQ, iova);
	pf = rvu_get_pf(pcifunc) & 0x1F;
	val = BIT_ULL(63) | BIT_ULL(14) | BIT_ULL(13) | pf << 8 |
	      ((pcifunc & RVU_PFVF_FUNC_MASK) & 0xFF);
	rvu_write64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_TXN_REQ, val);

	err = rvu_poll_reg(rvu, BLKADDR_RVUM, RVU_AF_SMMU_ADDR_RSP_STS, BIT_ULL(0), false);
	if (err) {
		dev_err(rvu->dev, "%s LMTLINE iova transulation failed\n", __func__);
		return err;
	}
	val = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_ADDR_RSP_STS);
	if (val & ~0x1ULL) {
		dev_err(rvu->dev, "%s LMTLINE iova transulation failed err:%llx\n", __func__, val);
		return -EIO;
	}
	/* PA[51:12] = RVU_AF_SMMU_TLN_FLIT1[60:21]
	 * PA[11:0] = IOVA[11:0]
	 */
	pa = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_TLN_FLIT1) >> 21;
	pa &= GENMASK_ULL(39, 0);
	*lmt_addr = (pa << 12) | (iova  & 0xFFF);

	return 0;
}

static int rvu_update_lmtaddr(struct rvu *rvu, u16 pcifunc, u64 lmt_addr)
{
	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
	u32 tbl_idx;
	int err = 0;
	u64 val;

	/* Read the current lmt addr of pcifunc */
	tbl_idx = rvu_get_lmtst_tbl_index(rvu, pcifunc);
	err = lmtst_map_table_ops(rvu, tbl_idx, &val, LMT_TBL_OP_READ);
	if (err) {
		dev_err(rvu->dev,
			"Failed to read LMT map table: index 0x%x err %d\n",
			tbl_idx, err);
		return err;
	}

	/* Storing the seondary's lmt base address as this needs to be
	 * reverted in FLR. Also making sure this default value doesn't
	 * get overwritten on multiple calls to this mailbox.
	 */
	if (!pfvf->lmt_base_addr)
		pfvf->lmt_base_addr = val;

	/* Update the LMT table with new addr */
	err = lmtst_map_table_ops(rvu, tbl_idx, &lmt_addr, LMT_TBL_OP_WRITE);
	if (err) {
		dev_err(rvu->dev,
			"Failed to update LMT map table: index 0x%x err %d\n",
			tbl_idx, err);
		return err;
	}
	return 0;
}

int rvu_mbox_handler_lmtst_tbl_setup(struct rvu *rvu,
				     struct lmtst_tbl_setup_req *req,
				     struct msg_rsp *rsp)
{
	u64 lmt_addr, val;
	u32 pri_tbl_idx;
	int err = 0;

	/* Check if PF_FUNC wants to use it's own local memory as LMTLINE
	 * region, if so, convert that IOVA to physical address and
	 * populate LMT table with that address
	 */
	if (req->use_local_lmt_region) {
		err = rvu_get_lmtaddr(rvu, req->hdr.pcifunc,
				      req->lmt_iova, &lmt_addr);
		if (err < 0)
			return err;

		/* Update the lmt addr for this PFFUNC in the LMT table */
		err = rvu_update_lmtaddr(rvu, req->hdr.pcifunc, lmt_addr);
		if (err)
			return err;
	}

	/* Reconfiguring lmtst map table in lmt region shared mode i.e. make
	 * multiple PF_FUNCs to share an LMTLINE region, so primary/base
	 * pcifunc (which is passed as an argument to mailbox) is the one
	 * whose lmt base address will be shared among other secondary
	 * pcifunc (will be the one who is calling this mailbox).
	 */
	if (req->base_pcifunc) {
		/* Calculating the LMT table index equivalent to primary
		 * pcifunc.
		 */
		pri_tbl_idx = rvu_get_lmtst_tbl_index(rvu, req->base_pcifunc);

		/* Read the base lmt addr of the primary pcifunc */
		err = lmtst_map_table_ops(rvu, pri_tbl_idx, &val,
					  LMT_TBL_OP_READ);
		if (err) {
			dev_err(rvu->dev,
				"Failed to read LMT map table: index 0x%x err %d\n",
				pri_tbl_idx, err);
			return err;
		}

		/* Update the base lmt addr of secondary with primary's base
		 * lmt addr.
		 */
		err = rvu_update_lmtaddr(rvu, req->hdr.pcifunc, val);
		if (err)
			return err;
	}

	return 0;
}

/* Resetting the lmtst map table to original base addresses */
void rvu_reset_lmt_map_tbl(struct rvu *rvu, u16 pcifunc)
{
	struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
	u32 tbl_idx;
	int err;

	if (is_rvu_otx2(rvu))
		return;

	if (pfvf->lmt_base_addr) {
		/* This corresponds to lmt map table index */
		tbl_idx = rvu_get_lmtst_tbl_index(rvu, pcifunc);
		/* Reverting back original lmt base addr for respective
		 * pcifunc.
		 */
		err = lmtst_map_table_ops(rvu, tbl_idx, &pfvf->lmt_base_addr,
					  LMT_TBL_OP_WRITE);
		if (err)
			dev_err(rvu->dev,
				"Failed to update LMT map table: index 0x%x err %d\n",
				tbl_idx, err);
		pfvf->lmt_base_addr = 0;
	}
}

int rvu_set_channels_base(struct rvu *rvu)
{
	struct rvu_hwinfo *hw = rvu->hw;
+10 −0
Original line number Diff line number Diff line
@@ -49,6 +49,11 @@
#define RVU_AF_PFX_VF_BAR4_ADDR             (0x5400 | (a) << 4)
#define RVU_AF_PFX_VF_BAR4_CFG              (0x5600 | (a) << 4)
#define RVU_AF_PFX_LMTLINE_ADDR             (0x5800 | (a) << 4)
#define RVU_AF_SMMU_ADDR_REQ		    (0x6000)
#define RVU_AF_SMMU_TXN_REQ		    (0x6008)
#define RVU_AF_SMMU_ADDR_RSP_STS	    (0x6010)
#define RVU_AF_SMMU_ADDR_TLN		    (0x6018)
#define RVU_AF_SMMU_TLN_FLIT1		    (0x6030)

/* Admin function's privileged PF/VF registers */
#define RVU_PRIV_CONST                      (0x8000000)
@@ -692,4 +697,9 @@
#define LBK_LINK_CFG_ID_MASK		GENMASK_ULL(11, 6)
#define LBK_LINK_CFG_BASE_MASK		GENMASK_ULL(5, 0)

/* APR */
#define	APR_AF_LMT_CFG			(0x000ull)
#define	APR_AF_LMT_MAP_BASE		(0x008ull)
#define	APR_AF_LMT_CTL			(0x010ull)

#endif /* RVU_REG_H */
Loading