Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e6c4955 authored by Carl Heymann's avatar Carl Heymann Committed by David S. Miller
Browse files

nfp: dump CPP, XPB and direct ME CSRs



- The spec defines CSR address ranges for these types.
- Dump each TLV chunk in the spec as a chunk that includes the spec and
  the data over the defined address range.

Signed-off-by: default avatarCarl Heymann <carl.heymann@netronome.com>
Reviewed-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarSimon Horman <simon.horman@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e9364d30
Loading
Loading
Loading
Loading
+102 −0
Original line number Diff line number Diff line
@@ -43,6 +43,9 @@
#define ALIGN8(x)	ALIGN(x, 8)

enum nfp_dumpspec_type {
	NFP_DUMPSPEC_TYPE_CPP_CSR = 0,
	NFP_DUMPSPEC_TYPE_XPB_CSR = 1,
	NFP_DUMPSPEC_TYPE_ME_CSR = 2,
	NFP_DUMPSPEC_TYPE_RTSYM = 4,
	NFP_DUMPSPEC_TYPE_HWINFO = 5,
	NFP_DUMPSPEC_TYPE_FWNAME = 6,
@@ -77,11 +80,27 @@ struct nfp_dump_common_cpp {
	__be32 dump_length;	/* total bytes to dump, aligned to reg size */
};

/* CSR dumpables */
struct nfp_dumpspec_csr {
	struct nfp_dump_tl tl;
	struct nfp_dump_common_cpp cpp;
	__be32 register_width;	/* in bits */
};

struct nfp_dumpspec_rtsym {
	struct nfp_dump_tl tl;
	char rtsym[0];
};

/* header for register dumpable */
struct nfp_dump_csr {
	struct nfp_dump_tl tl;
	struct nfp_dump_common_cpp cpp;
	__be32 register_width;	/* in bits */
	__be32 error;		/* error code encountered while reading */
	__be32 error_offset;	/* offset being read when error occurred */
};

struct nfp_dump_rtsym {
	struct nfp_dump_tl tl;
	struct nfp_dump_common_cpp cpp;
@@ -223,6 +242,20 @@ static int nfp_calc_hwinfo_field_sz(struct nfp_pf *pf, struct nfp_dump_tl *spec)
	return sizeof(struct nfp_dump_tl) + ALIGN8(key_len + strlen(value) + 2);
}

static bool nfp_csr_spec_valid(struct nfp_dumpspec_csr *spec_csr)
{
	u32 required_read_sz = sizeof(*spec_csr) - sizeof(spec_csr->tl);
	u32 available_sz = be32_to_cpu(spec_csr->tl.length);
	u32 reg_width;

	if (available_sz < required_read_sz)
		return false;

	reg_width = be32_to_cpu(spec_csr->register_width);

	return reg_width == 32 || reg_width == 64;
}

static int
nfp_calc_rtsym_dump_sz(struct nfp_pf *pf, struct nfp_dump_tl *spec)
{
@@ -248,6 +281,7 @@ nfp_calc_rtsym_dump_sz(struct nfp_pf *pf, struct nfp_dump_tl *spec)
static int
nfp_add_tlv_size(struct nfp_pf *pf, struct nfp_dump_tl *tl, void *param)
{
	struct nfp_dumpspec_csr *spec_csr;
	u32 *size = param;
	u32 hwinfo_size;

@@ -255,6 +289,16 @@ nfp_add_tlv_size(struct nfp_pf *pf, struct nfp_dump_tl *tl, void *param)
	case NFP_DUMPSPEC_TYPE_FWNAME:
		*size += nfp_calc_fwname_tlv_size(pf);
		break;
	case NFP_DUMPSPEC_TYPE_CPP_CSR:
	case NFP_DUMPSPEC_TYPE_XPB_CSR:
	case NFP_DUMPSPEC_TYPE_ME_CSR:
		spec_csr = (struct nfp_dumpspec_csr *)tl;
		if (!nfp_csr_spec_valid(spec_csr))
			*size += nfp_dump_error_tlv_size(tl);
		else
			*size += ALIGN8(sizeof(struct nfp_dump_csr)) +
				 ALIGN8(be32_to_cpu(spec_csr->cpp.dump_length));
		break;
	case NFP_DUMPSPEC_TYPE_RTSYM:
		*size += nfp_calc_rtsym_dump_sz(pf, tl);
		break;
@@ -417,6 +461,55 @@ static int nfp_dump_hwinfo_field(struct nfp_pf *pf, struct nfp_dump_tl *spec,
	return 0;
}

static int
nfp_dump_csr_range(struct nfp_pf *pf, struct nfp_dumpspec_csr *spec_csr,
		   struct nfp_dump_state *dump)
{
	struct nfp_dump_csr *dump_header = dump->p;
	u32 reg_sz, header_size, total_size;
	u32 cpp_rd_addr, max_rd_addr;
	int bytes_read;
	void *dest;
	u32 cpp_id;
	int err;

	if (!nfp_csr_spec_valid(spec_csr))
		return nfp_dump_error_tlv(&spec_csr->tl, -EINVAL, dump);

	reg_sz = be32_to_cpu(spec_csr->register_width) / BITS_PER_BYTE;
	header_size = ALIGN8(sizeof(*dump_header));
	total_size = header_size +
		     ALIGN8(be32_to_cpu(spec_csr->cpp.dump_length));
	dest = dump->p + header_size;

	err = nfp_add_tlv(be32_to_cpu(spec_csr->tl.type), total_size, dump);
	if (err)
		return err;

	dump_header->cpp = spec_csr->cpp;
	dump_header->register_width = spec_csr->register_width;

	cpp_id = nfp_get_numeric_cpp_id(&spec_csr->cpp.cpp_id);
	cpp_rd_addr = be32_to_cpu(spec_csr->cpp.offset);
	max_rd_addr = cpp_rd_addr + be32_to_cpu(spec_csr->cpp.dump_length);

	while (cpp_rd_addr < max_rd_addr) {
		bytes_read = nfp_cpp_read(pf->cpp, cpp_id, cpp_rd_addr, dest,
					  reg_sz);
		if (bytes_read != reg_sz) {
			if (bytes_read >= 0)
				bytes_read = -EIO;
			dump_header->error = cpu_to_be32(bytes_read);
			dump_header->error_offset = cpu_to_be32(cpp_rd_addr);
			break;
		}
		cpp_rd_addr += reg_sz;
		dest += reg_sz;
	}

	return 0;
}

static int
nfp_dump_single_rtsym(struct nfp_pf *pf, struct nfp_dumpspec_rtsym *spec,
		      struct nfp_dump_state *dump)
@@ -479,6 +572,7 @@ nfp_dump_for_tlv(struct nfp_pf *pf, struct nfp_dump_tl *tl, void *param)
{
	struct nfp_dumpspec_rtsym *spec_rtsym;
	struct nfp_dump_state *dump = param;
	struct nfp_dumpspec_csr *spec_csr;
	int err;

	switch (be32_to_cpu(tl->type)) {
@@ -487,6 +581,14 @@ nfp_dump_for_tlv(struct nfp_pf *pf, struct nfp_dump_tl *tl, void *param)
		if (err)
			return err;
		break;
	case NFP_DUMPSPEC_TYPE_CPP_CSR:
	case NFP_DUMPSPEC_TYPE_XPB_CSR:
	case NFP_DUMPSPEC_TYPE_ME_CSR:
		spec_csr = (struct nfp_dumpspec_csr *)tl;
		err = nfp_dump_csr_range(pf, spec_csr, dump);
		if (err)
			return err;
		break;
	case NFP_DUMPSPEC_TYPE_RTSYM:
		spec_rtsym = (struct nfp_dumpspec_rtsym *)tl;
		err = nfp_dump_single_rtsym(pf, spec_rtsym, dump);