lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20221116192705.660337-1-vladimir.oltean@nxp.com>
Date:   Wed, 16 Nov 2022 21:27:05 +0200
From:   Vladimir Oltean <vladimir.oltean@....com>
To:     netdev@...r.kernel.org
Cc:     Michal Kubecek <mkubecek@...e.cz>,
        Claudiu Manoil <claudiu.manoil@....com>
Subject: [PATCH v2 ethtool] fsl_enetc: add support for NXP ENETC driver

Add pretty printer for the registers which the enetc PF and VF drivers
support since their introduction in kernel v5.1. The selection of
registers parsed is the selection exported by the kernel as of v6.1-rc2.
Unparsed registers are printed as raw.

One register is printed field by field (MAC COMMAND_CONFIG), I didn't
have time/interest in printing more than 1. The rest are printed in hex.

Sample output:

$ ethtool -d eno0
SI mode register: 0x80000000
SI primary MAC address register 0: 0x59f0400
SI primary MAC address register 1: 0x27f6
SI control BDR mode register: 0x40000000
SI control BDR status register: 0x0
SI control BDR base address register 0: 0x8262f000
SI control BDR base address register 1: 0x20
SI control BDR producer index register: 0x3a
SI control BDR consumer index register: 0x3a
SI control BDR length register: 0x40
SI capability register 0: 0x10080008
SI capability register 1: 0x20002
SI uncorrectable error frame drop count register: 0x0
TX BDR 0 mode register: 0x80000200
TX BDR 0 status register: 0x0
TX BDR 0 base address register 0: 0xebfa0000
TX BDR 0 base address register 1: 0x0
TX BDR 0 producer index register: 0x12
TX BDR 0 consumer index register: 0x12
TX BDR 0 length register: 0x800
TX BDR 0 interrupt enable register: 0x1
TX BDR 0 interrupt coalescing register 0: 0x80000008
TX BDR 0 interrupt coalescing register 1: 0x3a980
(repeats for other TX rings)
RX BDR 0 mode register: 0x80000034
RX BDR 0 status register: 0x0
RX BDR 0 buffer size register: 0x680
RX BDR 0 consumer index register: 0x7ff
RX BDR 0 base address register 0: 0xec430000
RX BDR 0 base address register 1: 0x0
RX BDR 0 producer index register: 0x0
RX BDR 0 length register: 0x800
RX BDR 0 interrupt enable register: 0x1
RX BDR 0 interrupt coalescing register 0: 0x80000100
RX BDR 0 interrupt coalescing register 1: 0x1
(repeats for other RX rings)
Port mode register: 0x70200
Port status register: 0x0
Port SI promiscuous mode register: 0x0
Port SI0 primary MAC address register 0: 0x59f0400
Port SI0 primary MAC address register 1: 0x27f6
Port HTA transmit memory buffer allocation register: 0xc390
Port capability register 0: 0x10101b3c
Port capability register 1: 0x2070
Port SI0 configuration register 0: 0x3080008
Port RFS capability register: 0x2
Port traffic class 0 maximum SDU register: 0x2580
Port eMAC Command and Configuration Register: 0x8813
        MG 0
        RXSTP 0
        REG_LOWP_RXETY 0
        TX_LOWP_ENA 0
        SFD 0
        NO_LEN_CHK 0
        SEND_IDLE 0
        CNT_FRM_EN 0
        SWR 0
        TXP 1
        XGLP 0
        TX_ADDR_INS 0
        PAUSE_IGN 0
        PAUSE_FWD 0
        CRC 0
        PAD 0
        PROMIS 1
        WAN 0
        RX_EN 1
        TX_EN 1
Port eMAC Maximum Frame Length Register: 0x2580
Port eMAC Interface Mode Control Register: 0x1002

Signed-off-by: Vladimir Oltean <vladimir.oltean@....com>
---
v1->v2: s/1/1U/ in BIT() macro definition

 Makefile.am |   4 +-
 ethtool.c   |   2 +
 fsl_enetc.c | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 internal.h  |   3 +
 4 files changed, 266 insertions(+), 2 deletions(-)
 create mode 100644 fsl_enetc.c

diff --git a/Makefile.am b/Makefile.am
index 21fa91a58453..0bd41dd4600e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,8 +13,8 @@ ethtool_SOURCES = ethtool.c uapi/linux/ethtool.h internal.h \
 if ETHTOOL_ENABLE_PRETTY_DUMP
 ethtool_SOURCES += \
 		  amd8111e.c de2104x.c dsa.c e100.c e1000.c et131x.c igb.c	\
-		  fec.c fec_8xx.c ibm_emac.c ixgb.c ixgbe.c natsemi.c	\
-		  pcnet32.c realtek.c tg3.c marvell.c vioc.c	\
+		  fec.c fec_8xx.c fsl_enetc.c ibm_emac.c ixgb.c ixgbe.c \
+		  natsemi.c pcnet32.c realtek.c tg3.c marvell.c vioc.c \
 		  smsc911x.c at76c50x-usb.c sfc.c stmmac.c	\
 		  sff-common.c sff-common.h sfpid.c sfpdiag.c	\
 		  ixgbevf.c tse.c vmxnet3.c qsfp.c qsfp.h fjes.c lan78xx.c \
diff --git a/ethtool.c b/ethtool.c
index 96cef4630693..f15a7cef60ab 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -1131,6 +1131,8 @@ static const struct {
 	{ "bnxt_en", bnxt_dump_regs },
 	{ "cpsw-switch", cpsw_dump_regs },
 	{ "lan743x", lan743x_dump_regs },
+	{ "fsl_enetc", fsl_enetc_dump_regs },
+	{ "fsl_enetc_vf", fsl_enetc_dump_regs },
 };
 #endif
 
diff --git a/fsl_enetc.c b/fsl_enetc.c
new file mode 100644
index 000000000000..1180a664f777
--- /dev/null
+++ b/fsl_enetc.c
@@ -0,0 +1,259 @@
+/* Code to dump registers for the Freescale/NXP ENETC controller.
+ *
+ * Copyright 2022 NXP
+ */
+#include <stdio.h>
+#include "internal.h"
+
+#define BIT(x)			(1U << (x))
+
+enum enetc_bdr_type {TX, RX};
+#define ENETC_SIMR		0
+#define ENETC_SIPMAR0		0x80
+#define ENETC_SIPMAR1		0x84
+#define ENETC_SICBDRMR		0x800
+#define ENETC_SICBDRSR		0x804
+#define ENETC_SICBDRBAR0	0x810
+#define ENETC_SICBDRBAR1	0x814
+#define ENETC_SICBDRPIR		0x818
+#define ENETC_SICBDRCIR		0x81c
+#define ENETC_SICBDRLENR	0x820
+#define ENETC_SICAPR0		0x900
+#define ENETC_SICAPR1		0x904
+#define ENETC_SIUEFDCR		0xe28
+
+#define ENETC_BDR_OFF(i)	((i) * 0x200)
+#define ENETC_BDR(t, i, r)	(0x8000 + (t) * 0x100 + ENETC_BDR_OFF(i) + (r))
+
+/* RX BDR reg offsets */
+#define ENETC_RBMR		0
+#define ENETC_RBSR		0x4
+#define ENETC_RBBSR		0x8
+#define ENETC_RBCIR		0xc
+#define ENETC_RBBAR0		0x10
+#define ENETC_RBBAR1		0x14
+#define ENETC_RBPIR		0x18
+#define ENETC_RBLENR		0x20
+#define ENETC_RBIER		0xa0
+#define ENETC_RBICR0		0xa8
+#define ENETC_RBICR1		0xac
+
+/* TX BDR reg offsets */
+#define ENETC_TBMR		0
+#define ENETC_TBSR		0x4
+#define ENETC_TBBAR0		0x10
+#define ENETC_TBBAR1		0x14
+#define ENETC_TBPIR		0x18
+#define ENETC_TBCIR		0x1c
+#define ENETC_TBLENR		0x20
+#define ENETC_TBIER		0xa0
+#define ENETC_TBIDR		0xa4
+#define ENETC_TBICR0		0xa8
+#define ENETC_TBICR1		0xac
+
+/* Port registers */
+#define ENETC_PORT_BASE		0x10000
+#define ENETC_PMR		ENETC_PORT_BASE + 0x0000
+#define ENETC_PSR		ENETC_PORT_BASE + 0x0004
+#define ENETC_PSIPMR		ENETC_PORT_BASE + 0x0018
+#define ENETC_PSIPMAR0(n)	ENETC_PORT_BASE + (0x0100 + (n) * 0x8) /* n = SI index */
+#define ENETC_PSIPMAR1(n)	ENETC_PORT_BASE + (0x0104 + (n) * 0x8)
+#define ENETC_PTXMBAR		ENETC_PORT_BASE + 0x0608
+#define ENETC_PCAPR0		ENETC_PORT_BASE + 0x0900
+#define ENETC_PCAPR1		ENETC_PORT_BASE + 0x0904
+#define ENETC_PSICFGR0(n)	ENETC_PORT_BASE + (0x0940 + (n) * 0xc)  /* n = SI index */
+
+#define ENETC_PRFSCAPR		ENETC_PORT_BASE + 0x1804
+#define ENETC_PTCMSDUR(n)	ENETC_PORT_BASE + (0x2020 + (n) * 4) /* n = TC index [0..7] */
+
+#define ENETC_PM0_CMD_CFG	ENETC_PORT_BASE + 0x8008
+#define ENETC_PM0_CMD_TX_EN		BIT(0)
+#define ENETC_PM0_CMD_RX_EN		BIT(1)
+#define ENETC_PM0_CMD_WAN		BIT(3)
+#define ENETC_PM0_CMD_PROMISC		BIT(4)
+#define ENETC_PM0_CMD_PAD		BIT(5)
+#define ENETC_PM0_CMD_CRC		BIT(6)
+#define ENETC_PM0_CMD_PAUSE_FWD		BIT(7)
+#define ENETC_PM0_CMD_PAUSE_IGN		BIT(8)
+#define ENETC_PM0_CMD_TX_ADDR_INS	BIT(9)
+#define ENETC_PM0_CMD_XGLP		BIT(10)
+#define ENETC_PM0_CMD_TXP		BIT(11)
+#define ENETC_PM0_CMD_SWR		BIT(12)
+#define ENETC_PM0_CMD_CNT_FRM_EN	BIT(13)
+#define ENETC_PM0_CMD_SEND_IDLE		BIT(16)
+#define ENETC_PM0_CMD_NO_LEN_CHK	BIT(17)
+#define ENETC_PM0_CMD_SFD		BIT(21)
+#define ENETC_PM0_CMD_TX_LOWP_ENA	BIT(23)
+#define ENETC_PM0_CMD_REG_LOWP_RXETY	BIT(24)
+#define ENETC_PM0_CMD_RXSTP		BIT(29)
+#define ENETC_PM0_CMD_MG		BIT(31)
+
+#define ENETC_PM0_MAXFRM	ENETC_PORT_BASE + 0x8014
+#define ENETC_PM0_IF_MODE	ENETC_PORT_BASE + 0x8300
+
+struct enetc_register {
+	u32 addr;
+	const char *name;
+	void (*decode)(u32 val, char *buf);
+};
+
+#define REG(_reg, _name)	{ .addr = (_reg), .name = (_name) }
+
+#define REG_DEC(_reg, _name, _decode) \
+	{ .addr = (_reg), .name = (_name), .decode = (_decode) }
+
+static void decode_cmd_cfg(u32 val, char *buf)
+{
+	sprintf(buf, "\tMG %d\n\tRXSTP %d\n\tREG_LOWP_RXETY %d\n"
+		"\tTX_LOWP_ENA %d\n\tSFD %d\n\tNO_LEN_CHK %d\n\tSEND_IDLE %d\n"
+		"\tCNT_FRM_EN %d\n\tSWR %d\n\tTXP %d\n\tXGLP %d\n"
+		"\tTX_ADDR_INS %d\n\tPAUSE_IGN %d\n\tPAUSE_FWD %d\n\tCRC %d\n"
+		"\tPAD %d\n\tPROMIS %d\n\tWAN %d\n\tRX_EN %d\n\tTX_EN %d\n",
+		!!(val & ENETC_PM0_CMD_MG),
+		!!(val & ENETC_PM0_CMD_RXSTP),
+		!!(val & ENETC_PM0_CMD_REG_LOWP_RXETY),
+		!!(val & ENETC_PM0_CMD_TX_LOWP_ENA),
+		!!(val & ENETC_PM0_CMD_SFD),
+		!!(val & ENETC_PM0_CMD_NO_LEN_CHK),
+		!!(val & ENETC_PM0_CMD_SEND_IDLE),
+		!!(val & ENETC_PM0_CMD_CNT_FRM_EN),
+		!!(val & ENETC_PM0_CMD_SWR),
+		!!(val & ENETC_PM0_CMD_TXP),
+		!!(val & ENETC_PM0_CMD_XGLP),
+		!!(val & ENETC_PM0_CMD_TX_ADDR_INS),
+		!!(val & ENETC_PM0_CMD_PAUSE_IGN),
+		!!(val & ENETC_PM0_CMD_PAUSE_FWD),
+		!!(val & ENETC_PM0_CMD_CRC),
+		!!(val & ENETC_PM0_CMD_PAD),
+		!!(val & ENETC_PM0_CMD_PROMISC),
+		!!(val & ENETC_PM0_CMD_WAN),
+		!!(val & ENETC_PM0_CMD_RX_EN),
+		!!(val & ENETC_PM0_CMD_TX_EN));
+}
+
+#define RXBDR_REGS(_i) \
+	REG(ENETC_BDR(RX, (_i), ENETC_RBMR), "RX BDR " #_i " mode register"), \
+	REG(ENETC_BDR(RX, (_i), ENETC_RBSR), "RX BDR " #_i " status register"), \
+	REG(ENETC_BDR(RX, (_i), ENETC_RBBSR), "RX BDR " #_i " buffer size register"), \
+	REG(ENETC_BDR(RX, (_i), ENETC_RBPIR), "RX BDR " #_i " producer index register"), \
+	REG(ENETC_BDR(RX, (_i), ENETC_RBCIR), "RX BDR " #_i " consumer index register"), \
+	REG(ENETC_BDR(RX, (_i), ENETC_RBBAR0), "RX BDR " #_i " base address register 0"), \
+	REG(ENETC_BDR(RX, (_i), ENETC_RBBAR1), "RX BDR " #_i " base address register 1"), \
+	REG(ENETC_BDR(RX, (_i), ENETC_RBLENR), "RX BDR " #_i " length register"), \
+	REG(ENETC_BDR(RX, (_i), ENETC_RBIER), "RX BDR " #_i " interrupt enable register"), \
+	REG(ENETC_BDR(RX, (_i), ENETC_RBICR0), "RX BDR " #_i " interrupt coalescing register 0"), \
+	REG(ENETC_BDR(RX, (_i), ENETC_RBICR1), "RX BDR " #_i " interrupt coalescing register 1")
+
+#define TXBDR_REGS(_i) \
+	REG(ENETC_BDR(TX, (_i), ENETC_TBMR), "TX BDR " #_i " mode register"), \
+	REG(ENETC_BDR(TX, (_i), ENETC_TBSR), "TX BDR " #_i " status register"), \
+	REG(ENETC_BDR(TX, (_i), ENETC_TBBAR0), "TX BDR " #_i " base address register 0"), \
+	REG(ENETC_BDR(TX, (_i), ENETC_TBBAR1), "TX BDR " #_i " base address register 1"), \
+	REG(ENETC_BDR(TX, (_i), ENETC_TBPIR), "TX BDR " #_i " producer index register"), \
+	REG(ENETC_BDR(TX, (_i), ENETC_TBCIR), "TX BDR " #_i " consumer index register"), \
+	REG(ENETC_BDR(TX, (_i), ENETC_TBLENR), "TX BDR " #_i " length register"), \
+	REG(ENETC_BDR(TX, (_i), ENETC_TBIER), "TX BDR " #_i " interrupt enable register"), \
+	REG(ENETC_BDR(TX, (_i), ENETC_TBICR0), "TX BDR " #_i " interrupt coalescing register 0"), \
+	REG(ENETC_BDR(TX, (_i), ENETC_TBICR1), "TX BDR " #_i " interrupt coalescing register 1")
+
+static const struct enetc_register known_enetc_regs[] = {
+	REG(ENETC_SIMR, "SI mode register"),
+	REG(ENETC_SIPMAR0, "SI primary MAC address register 0"),
+	REG(ENETC_SIPMAR1, "SI primary MAC address register 1"),
+	REG(ENETC_SICBDRMR, "SI control BDR mode register"),
+	REG(ENETC_SICBDRSR, "SI control BDR status register"),
+	REG(ENETC_SICBDRBAR0, "SI control BDR base address register 0"),
+	REG(ENETC_SICBDRBAR1, "SI control BDR base address register 1"),
+	REG(ENETC_SICBDRPIR, "SI control BDR producer index register"),
+	REG(ENETC_SICBDRCIR, "SI control BDR consumer index register"),
+	REG(ENETC_SICBDRLENR, "SI control BDR length register"),
+	REG(ENETC_SICAPR0, "SI capability register 0"),
+	REG(ENETC_SICAPR1, "SI capability register 1"),
+	REG(ENETC_SIUEFDCR, "SI uncorrectable error frame drop count register"),
+
+	TXBDR_REGS(0), TXBDR_REGS(1), TXBDR_REGS(2), TXBDR_REGS(3),
+	TXBDR_REGS(4), TXBDR_REGS(5), TXBDR_REGS(6), TXBDR_REGS(7),
+	TXBDR_REGS(8), TXBDR_REGS(9), TXBDR_REGS(10), TXBDR_REGS(11),
+	TXBDR_REGS(12), TXBDR_REGS(13), TXBDR_REGS(14), TXBDR_REGS(15),
+
+	RXBDR_REGS(0), RXBDR_REGS(1), RXBDR_REGS(2), RXBDR_REGS(3),
+	RXBDR_REGS(4), RXBDR_REGS(5), RXBDR_REGS(6), RXBDR_REGS(7),
+	RXBDR_REGS(8), RXBDR_REGS(9), RXBDR_REGS(10), RXBDR_REGS(11),
+	RXBDR_REGS(12), RXBDR_REGS(13), RXBDR_REGS(14), RXBDR_REGS(15),
+
+	REG(ENETC_PMR, "Port mode register"),
+	REG(ENETC_PSR, "Port status register"),
+	REG(ENETC_PSIPMR, "Port SI promiscuous mode register"),
+	REG(ENETC_PSIPMAR0(0), "Port SI0 primary MAC address register 0"),
+	REG(ENETC_PSIPMAR1(0), "Port SI0 primary MAC address register 1"),
+	REG(ENETC_PTXMBAR, "Port HTA transmit memory buffer allocation register"),
+	REG(ENETC_PCAPR0, "Port capability register 0"),
+	REG(ENETC_PCAPR1, "Port capability register 1"),
+	REG(ENETC_PSICFGR0(0), "Port SI0 configuration register 0"),
+	REG(ENETC_PRFSCAPR, "Port RFS capability register"),
+	REG(ENETC_PTCMSDUR(0), "Port traffic class 0 maximum SDU register"),
+	REG_DEC(ENETC_PM0_CMD_CFG, "Port eMAC Command and Configuration Register",
+		decode_cmd_cfg),
+	REG(ENETC_PM0_MAXFRM, "Port eMAC Maximum Frame Length Register"),
+	REG(ENETC_PM0_IF_MODE, "Port eMAC Interface Mode Control Register"),
+};
+
+static void decode_known_reg(const struct enetc_register *reg, u32 val)
+{
+	char buf[512];
+
+	reg->decode(val, buf);
+	fprintf(stdout, "%s: 0x%x\n%s", reg->name, val, buf);
+}
+
+static void dump_known_reg(const struct enetc_register *reg, u32 val)
+{
+	fprintf(stdout, "%s: 0x%x\n", reg->name, val);
+}
+
+static void dump_unknown_reg(u32 addr, u32 val)
+{
+	fprintf(stdout, "Reg 0x%x: 0x%x\n", addr, val);
+}
+
+static void dump_reg(u32 addr, u32 val)
+{
+	const struct enetc_register *reg;
+	u32 i;
+
+	for (i = 0; i < ARRAY_SIZE(known_enetc_regs); i++) {
+		reg = &known_enetc_regs[i];
+		if (reg->addr == addr) {
+			if (reg->decode)
+				decode_known_reg(reg, val);
+			else
+				dump_known_reg(reg, val);
+			return;
+		}
+	}
+
+	dump_unknown_reg(addr, val);
+}
+
+/* Registers are structured in an array of key/value u32 pairs.
+ * Compare each key to our list of known registers, or print it
+ * as a raw address otherwise.
+ */
+int fsl_enetc_dump_regs(struct ethtool_drvinfo *info __maybe_unused,
+			struct ethtool_regs *regs)
+{
+	u32 *data = (u32 *)regs->data;
+	u32 len = regs->len;
+
+	if (len % 8) {
+		fprintf(stdout, "Expected length to be multiple of 8 bytes\n");
+		return -1;
+	}
+
+	while (len) {
+		dump_reg(data[0], data[1]);
+		data += 2; len -= 8;
+	}
+
+	return 0;
+}
diff --git a/internal.h b/internal.h
index 9fa6d80b4b29..dd7d6ac70ad4 100644
--- a/internal.h
+++ b/internal.h
@@ -406,6 +406,9 @@ int dsa_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
 /* i.MX Fast Ethernet Controller */
 int fec_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
 
+/* Freescale/NXP ENETC Ethernet Controller */
+int fsl_enetc_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
+
 /* Intel(R) Ethernet Controller I225-LM/I225-V adapter family */
 int igc_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
 
-- 
2.34.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ