Merge RP1A.191114.001

Change-Id: I959cffe1d5cc0cd5c7e6a112b01cc2226c3604a6
diff --git a/.gitignore b/.gitignore
index f1165a2..c4df588 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,6 @@
 .deps
 test-*.log
 test-*.trs
+
+.*.swp
+*.patch
diff --git a/Android.bp b/Android.bp
index 7ab34e2..6bbb05d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -36,11 +36,9 @@
         "vmxnet3.c",
     ],
     cflags: [
-        "-Wno-unused-parameter",
         "-Wno-missing-field-initializers",
-        "-Wno-pointer-arith",
         "-DPACKAGE=\"ethtool\"",
-        "-DVERSION=\"5.2\"",
+        "-DVERSION=\"5.3\"",
         "-std=gnu11",
     ]
 }
diff --git a/NEWS b/NEWS
index 6b2248f..70f2396 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+Version 5.3 - September 23, 2019
+	* Feature: igb: dump RR2DCDELAY register
+	* Feature: dump nested registers
+
 Version 5.2 - July 25, 2019
 	* Feature: Add 100BaseT1 and 1000BaseT1 link modes
 	* Feature: Use standard file location macros in ethtool.spec
diff --git a/amd8111e.c b/amd8111e.c
index 23478f0..5a056b3 100644
--- a/amd8111e.c
+++ b/amd8111e.c
@@ -152,7 +152,8 @@
 #define PHY_SPEED_100		0x3
 
 
-int amd8111e_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int amd8111e_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		       struct ethtool_regs *regs)
 {
 
 	u32 *reg_buff = (u32 *)regs->data;
diff --git a/at76c50x-usb.c b/at76c50x-usb.c
index 39e24a4..0121e98 100644
--- a/at76c50x-usb.c
+++ b/at76c50x-usb.c
@@ -12,8 +12,8 @@
         "     505AMX",
 };
 
-int
-at76c50x_usb_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int at76c50x_usb_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+			   struct ethtool_regs *regs)
 {
 	u8 version = (u8)(regs->version >> 24);
 	u8 rev_id = (u8)(regs->version);
diff --git a/configure.ac b/configure.ac
index 2127fdb..56e4683 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-AC_INIT(ethtool, 5.2, netdev@vger.kernel.org)
+AC_INIT(ethtool, 5.3, netdev@vger.kernel.org)
 AC_PREREQ(2.52)
 AC_CONFIG_SRCDIR([ethtool.c])
 AM_INIT_AUTOMAKE([gnu])
diff --git a/de2104x.c b/de2104x.c
index 856e0c0..cc03533 100644
--- a/de2104x.c
+++ b/de2104x.c
@@ -111,8 +111,8 @@
 	}
 }
 
-static void
-de21040_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+static void de21040_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+			      struct ethtool_regs *regs)
 {
 	u32 tmp, v, *data = (u32 *)regs->data;
 
@@ -417,8 +417,8 @@
 		v & (1<<0) ? "      Jabber disable\n" : "");
 }
 
-static void
-de21041_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+static void de21041_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+			      struct ethtool_regs *regs)
 {
 	u32 tmp, v, *data = (u32 *)regs->data;
 
diff --git a/dsa.c b/dsa.c
index 02a10dd..50a171b 100644
--- a/dsa.c
+++ b/dsa.c
@@ -674,7 +674,8 @@
 #undef FIELD
 #undef REG
 
-int dsa_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int dsa_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		  struct ethtool_regs *regs)
 {
 	/* DSA per-driver register dump */
 	if (!dsa_mv88e6xxx_dump_regs(regs))
diff --git a/e100.c b/e100.c
index b982e79..540ae35 100644
--- a/e100.c
+++ b/e100.c
@@ -36,8 +36,8 @@
 #define CU_CMD			0x00F0
 #define RU_CMD			0x0007
 
-int
-e100_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int e100_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		   struct ethtool_regs *regs)
 {
 	u32 *regs_buff = (u32 *)regs->data;
 	u8 version = (u8)(regs->version >> 24);
diff --git a/e1000.c b/e1000.c
index afeb7f8..91e5bc1 100644
--- a/e1000.c
+++ b/e1000.c
@@ -254,8 +254,7 @@
 	e1000_num_macs
 };
 
-static enum e1000_mac_type
-e1000_get_mac_type(u16 device_id, u8 revision_id)
+static enum e1000_mac_type e1000_get_mac_type(u16 device_id)
 {
 	enum e1000_mac_type mac_type = e1000_undefined;
 
@@ -364,12 +363,12 @@
 	return mac_type;
 }
 
-int
-e1000_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int e1000_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		    struct ethtool_regs *regs)
 {
 	u32 *regs_buff = (u32 *)regs->data;
 	u16 hw_device_id = (u16)regs->version;
-	u8 hw_revision_id = (u8)(regs->version >> 16);
+	/* u8 hw_revision_id = (u8)(regs->version >> 16); */
 	u8 version = (u8)(regs->version >> 24);
 	enum e1000_mac_type mac_type;
 	u32 reg;
@@ -377,7 +376,7 @@
 	if (version != 1)
 		return -1;
 
-	mac_type = e1000_get_mac_type(hw_device_id, hw_revision_id);
+	mac_type = e1000_get_mac_type(hw_device_id);
 
 	if(mac_type == e1000_undefined)
 		return -1;
diff --git a/et131x.c b/et131x.c
index 36abaa2..1b06071 100644
--- a/et131x.c
+++ b/et131x.c
@@ -2,7 +2,8 @@
 #include <string.h>
 #include "internal.h"
 
-int et131x_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int et131x_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		     struct ethtool_regs *regs)
 {
 	u8 version = (u8)(regs->version >> 24);
 	u32 *reg = (u32 *)regs->data;
diff --git a/ethtool-copy.h b/ethtool-copy.h
index ad16e8f..9afd2e6 100644
--- a/ethtool-copy.h
+++ b/ethtool-copy.h
@@ -257,10 +257,32 @@
 #define ETHTOOL_PHY_FAST_LINK_DOWN_ON	0
 #define ETHTOOL_PHY_FAST_LINK_DOWN_OFF	0xff
 
+/* Energy Detect Power Down (EDPD) is a feature supported by some PHYs, where
+ * the PHY's RX & TX blocks are put into a low-power mode when there is no
+ * link detected (typically cable is un-plugged). For RX, only a minimal
+ * link-detection is available, and for TX the PHY wakes up to send link pulses
+ * to avoid any lock-ups in case the peer PHY may also be running in EDPD mode.
+ *
+ * Some PHYs may support configuration of the wake-up interval for TX pulses,
+ * and some PHYs may support only disabling TX pulses entirely. For the latter
+ * a special value is required (ETHTOOL_PHY_EDPD_NO_TX) so that this can be
+ * configured from userspace (should the user want it).
+ *
+ * The interval units for TX wake-up are in milliseconds, since this should
+ * cover a reasonable range of intervals:
+ *  - from 1 millisecond, which does not sound like much of a power-saver
+ *  - to ~65 seconds which is quite a lot to wait for a link to come up when
+ *    plugging a cable
+ */
+#define ETHTOOL_PHY_EDPD_DFLT_TX_MSECS		0xffff
+#define ETHTOOL_PHY_EDPD_NO_TX			0xfffe
+#define ETHTOOL_PHY_EDPD_DISABLE		0
+
 enum phy_tunable_id {
 	ETHTOOL_PHY_ID_UNSPEC,
 	ETHTOOL_PHY_DOWNSHIFT,
 	ETHTOOL_PHY_FAST_LINK_DOWN,
+	ETHTOOL_PHY_EDPD,
 	/*
 	 * Add your fresh new phy tunable attribute above and remember to update
 	 * phy_tunable_strings[] in net/core/ethtool.c
@@ -1481,8 +1503,8 @@
 	ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT = 64,
 	ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT	 = 65,
 	ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT	 = 66,
-	ETHTOOL_LINK_MODE_100baseT1_Full_BIT             = 67,
-	ETHTOOL_LINK_MODE_1000baseT1_Full_BIT            = 68,
+	ETHTOOL_LINK_MODE_100baseT1_Full_BIT		 = 67,
+	ETHTOOL_LINK_MODE_1000baseT1_Full_BIT		 = 68,
 
 	/* must be last entry */
 	__ETHTOOL_LINK_MODE_MASK_NBITS
@@ -1712,8 +1734,8 @@
 #define ETH_MODULE_SFF_8436		0x4
 #define ETH_MODULE_SFF_8436_LEN		256
 
-#define ETH_MODULE_SFF_8636_MAX_LEN	640
-#define ETH_MODULE_SFF_8436_MAX_LEN	640
+#define ETH_MODULE_SFF_8636_MAX_LEN     640
+#define ETH_MODULE_SFF_8436_MAX_LEN     640
 
 /* Reset flags */
 /* The reset() operation must clear the flags for the components which
diff --git a/ethtool.8.in b/ethtool.8.in
index cd3be91..062695a 100644
--- a/ethtool.8.in
+++ b/ethtool.8.in
@@ -113,7 +113,7 @@
 .  hy \\n(HY
 ..
 .
-.TH ETHTOOL 8 "July 2019" "Ethtool version @VERSION@"
+.TH ETHTOOL 8 "September 2019" "Ethtool version @VERSION@"
 .SH NAME
 ethtool \- query or control network driver and hardware settings
 .
@@ -362,11 +362,17 @@
 .A1 on off
 .BN msecs
 .RB ]
+.RB [
+.B energy\-detect\-power\-down
+.A1 on off
+.BN msecs
+.RB ]
 .HP
 .B ethtool \-\-get\-phy\-tunable
 .I devname
 .RB [ downshift ]
 .RB [ fast-link-down ]
+.RB [ energy-detect-power-down ]
 .HP
 .B ethtool \-\-reset
 .I devname
@@ -1100,6 +1106,24 @@
 	Sets the period after which the link is reported as down. Note that the PHY may choose
 	the closest supported value. Only on reading back the tunable do you get the actual value.
 .TE
+.TP
+.A2 energy-detect-power-down on off
+Specifies whether Energy Detect Power Down (EDPD) should be enabled (if supported).
+This will put the RX and TX circuit blocks into a low power mode, and the PHY will
+wake up periodically to send link pulses to avoid any lock-up situation with a peer
+PHY that may also have EDPD enabled. By default, this setting will also enable the
+periodic transmission of TX pulses.
+.TS
+nokeep;
+lB	l.
+.BI msecs \ N
+	Some PHYs support configuration of the wake-up interval to send TX pulses.
+	This setting allows the control of this interval, and 0 disables TX pulses
+	if the PHY supports this. Disabling TX pulses can create a lock-up situation
+	where neither of the PHYs wakes the other one. If unspecified the default
+	value (in milliseconds) will be used by the PHY.
+.TE
+.TP
 .PD
 .RE
 .TP
@@ -1122,6 +1146,10 @@
 before a broken link is reported as being down.
 
 Gets the PHY Fast Link Down status / period.
+.TP
+.B energy\-detect\-power\-down
+Gets the current configured setting for Energy Detect Power Down (if supported).
+
 .RE
 .TP
 .B \-\-reset
diff --git a/ethtool.c b/ethtool.c
index 05fe05a..acf183d 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -470,7 +470,7 @@
 	return flow_type;
 }
 
-static int do_version(struct cmd_context *ctx)
+static int do_version(struct cmd_context *ctx maybe_unused)
 {
 	fprintf(stdout,
 		PACKAGE " version " VERSION
@@ -1245,7 +1245,7 @@
 
 	if (gregs_dump_raw) {
 		fwrite(regs->data, regs->len, 1, stdout);
-		return 0;
+		goto nested;
 	}
 
 	if (!gregs_dump_hex)
@@ -1253,7 +1253,7 @@
 			if (!strncmp(driver_list[i].name, info->driver,
 				     ETHTOOL_BUSINFO_LEN)) {
 				if (driver_list[i].func(info, regs) == 0)
-					return 0;
+					goto nested;
 				/* This version (or some other
 				 * variation in the dump format) is
 				 * not handled; fall back to hex
@@ -1263,10 +1263,20 @@
 
 	dump_hex(stdout, regs->data, regs->len, 0);
 
+nested:
+	/* Recurse dump if some drvinfo and regs structures are nested */
+	if (info->regdump_len > regs->len + sizeof(*info) + sizeof(*regs)) {
+		info = (struct ethtool_drvinfo *)(&regs->data[0] + regs->len);
+		regs = (struct ethtool_regs *)(&regs->data[0] + regs->len + sizeof(*info));
+
+		return dump_regs(gregs_dump_raw, gregs_dump_hex, info, regs);
+	}
+
 	return 0;
 }
 
-static int dump_eeprom(int geeprom_dump_raw, struct ethtool_drvinfo *info,
+static int dump_eeprom(int geeprom_dump_raw,
+		       struct ethtool_drvinfo *info maybe_unused,
 		       struct ethtool_eeprom *ee)
 {
 	if (geeprom_dump_raw) {
@@ -4888,6 +4898,30 @@
 		else
 			fprintf(stdout, "Fast Link Down enabled, %d msecs\n",
 				cont.msecs);
+	} else if (!strcmp(argp[0], "energy-detect-power-down")) {
+		struct {
+			struct ethtool_tunable ds;
+			u16 msecs;
+		} cont;
+
+		cont.ds.cmd = ETHTOOL_PHY_GTUNABLE;
+		cont.ds.id = ETHTOOL_PHY_EDPD;
+		cont.ds.type_id = ETHTOOL_TUNABLE_U16;
+		cont.ds.len = 2;
+		if (send_ioctl(ctx, &cont.ds) < 0) {
+			perror("Cannot Get PHY Energy Detect Power Down value");
+			return 87;
+		}
+
+		if (cont.msecs == ETHTOOL_PHY_EDPD_DISABLE)
+			fprintf(stdout, "Energy Detect Power Down: disabled\n");
+		else if (cont.msecs == ETHTOOL_PHY_EDPD_NO_TX)
+			fprintf(stdout,
+				"Energy Detect Power Down: enabled, TX disabled\n");
+		else
+			fprintf(stdout,
+				"Energy Detect Power Down: enabled, TX %u msecs\n",
+				cont.msecs);
 	} else {
 		exit_bad_args();
 	}
@@ -5009,7 +5043,10 @@
 	return 1;
 }
 
-static int parse_named_u8(struct cmd_context *ctx, const char *name, u8 *val)
+static int parse_named_uint(struct cmd_context *ctx,
+			    const char *name,
+			    unsigned long long *val,
+			    unsigned long long max)
 {
 	if (ctx->argc < 2)
 		return 0;
@@ -5017,7 +5054,7 @@
 	if (strcmp(*ctx->argp, name))
 		return 0;
 
-	*val = get_uint_range(*(ctx->argp + 1), 0, 0xff);
+	*val = get_uint_range(*(ctx->argp + 1), 0, max);
 
 	ctx->argc -= 2;
 	ctx->argp += 2;
@@ -5025,6 +5062,30 @@
 	return 1;
 }
 
+static int parse_named_u8(struct cmd_context *ctx, const char *name, u8 *val)
+{
+	unsigned long long val1;
+	int ret;
+
+	ret = parse_named_uint(ctx, name, &val1, 0xff);
+	if (ret)
+		*val = val1;
+
+	return ret;
+}
+
+static int parse_named_u16(struct cmd_context *ctx, const char *name, u16 *val)
+{
+	unsigned long long val1;
+	int ret;
+
+	ret = parse_named_uint(ctx, name, &val1, 0xffff);
+	if (ret)
+		*val = val1;
+
+	return ret;
+}
+
 static int do_set_phy_tunable(struct cmd_context *ctx)
 {
 	int err = 0;
@@ -5032,6 +5093,8 @@
 	u8 ds_changed = 0, ds_has_cnt = 0, ds_enable = 0;
 	u8 fld_changed = 0, fld_enable = 0;
 	u8 fld_msecs = ETHTOOL_PHY_FAST_LINK_DOWN_ON;
+	u8 edpd_changed = 0, edpd_enable = 0;
+	u16 edpd_tx_interval = ETHTOOL_PHY_EDPD_DFLT_TX_MSECS;
 
 	/* Parse arguments */
 	if (parse_named_bool(ctx, "downshift", &ds_enable)) {
@@ -5041,6 +5104,11 @@
 		fld_changed = 1;
 		if (fld_enable)
 			parse_named_u8(ctx, "msecs", &fld_msecs);
+	} else if (parse_named_bool(ctx, "energy-detect-power-down",
+				    &edpd_enable)) {
+		edpd_changed = 1;
+		if (edpd_enable)
+			parse_named_u16(ctx, "msecs", &edpd_tx_interval);
 	} else {
 		exit_bad_args();
 	}
@@ -5065,6 +5133,16 @@
 			fld_msecs = ETHTOOL_PHY_FAST_LINK_DOWN_OFF;
 		else if (fld_msecs == ETHTOOL_PHY_FAST_LINK_DOWN_OFF)
 			exit_bad_args();
+	} else if (edpd_changed) {
+		if (!edpd_enable)
+			edpd_tx_interval = ETHTOOL_PHY_EDPD_DISABLE;
+		else if (edpd_tx_interval == 0)
+			edpd_tx_interval = ETHTOOL_PHY_EDPD_NO_TX;
+		else if (edpd_tx_interval > ETHTOOL_PHY_EDPD_NO_TX) {
+			fprintf(stderr, "'msecs' max value is %d.\n",
+				(ETHTOOL_PHY_EDPD_NO_TX - 1));
+			exit_bad_args();
+		}
 	}
 
 	/* Do it */
@@ -5100,6 +5178,22 @@
 			perror("Cannot Set PHY Fast Link Down value");
 			err = 87;
 		}
+	} else if (edpd_changed) {
+		struct {
+			struct ethtool_tunable fld;
+			u16 msecs;
+		} cont;
+
+		cont.fld.cmd = ETHTOOL_PHY_STUNABLE;
+		cont.fld.id = ETHTOOL_PHY_EDPD;
+		cont.fld.type_id = ETHTOOL_TUNABLE_U16;
+		cont.fld.len = 2;
+		cont.msecs = edpd_tx_interval;
+		err = send_ioctl(ctx, &cont.fld);
+		if (err < 0) {
+			perror("Cannot Set PHY Energy Detect Power Down");
+			err = 87;
+		}
 	}
 
 	return err;
@@ -5352,10 +5446,12 @@
 	  "		[ tx-timer %d ]\n"},
 	{ "--set-phy-tunable", 1, do_set_phy_tunable, "Set PHY tunable",
 	  "		[ downshift on|off [count N] ]\n"
-	  "		[ fast-link-down on|off [msecs N] ]\n"},
+	  "		[ fast-link-down on|off [msecs N] ]\n"
+	  "		[ energy-detect-power-down on|off [msecs N] ]\n"},
 	{ "--get-phy-tunable", 1, do_get_phy_tunable, "Get PHY tunable",
 	  "		[ downshift ]\n"
-	  "		[ fast-link-down ]\n"},
+	  "		[ fast-link-down ]\n"
+	  "		[ energy-detect-power-down ]\n"},
 	{ "--reset", 1, do_reset, "Reset components",
 	  "		[ flags %x ]\n"
 	  "		[ mgmt ]\n"
@@ -5389,7 +5485,7 @@
 	{}
 };
 
-static int show_usage(struct cmd_context *ctx)
+static int show_usage(struct cmd_context *ctx maybe_unused)
 {
 	int i;
 
@@ -5412,7 +5508,7 @@
 	return 0;
 }
 
-static int find_option(int argc, char **argp)
+static int find_option(char *arg)
 {
 	const char *opt;
 	size_t len;
@@ -5422,8 +5518,7 @@
 		opt = args[k].opts;
 		for (;;) {
 			len = strcspn(opt, "|");
-			if (strncmp(*argp, opt, len) == 0 &&
-			    (*argp)[len] == 0)
+			if (strncmp(arg, opt, len) == 0 && arg[len] == 0)
 				return k;
 
 			if (opt[len] == 0)
@@ -5572,7 +5667,7 @@
 		ctx->argp++;
 	}
 
-	i = find_option(ctx->argc, ctx->argp);
+	i = find_option(ctx->argp[0]);
 	if (i < 0)
 		exit_bad_args();
 
@@ -5624,7 +5719,7 @@
 	if (argc == 0)
 		exit_bad_args();
 
-	k = find_option(argc, argp);
+	k = find_option(*argp);
 	if (k >= 0) {
 		argp++;
 		argc--;
diff --git a/fec.c b/fec.c
index 01b1d34..22bc09f 100644
--- a/fec.c
+++ b/fec.c
@@ -194,7 +194,8 @@
 #undef FIELD
 #undef REG
 
-int fec_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int fec_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		  struct ethtool_regs *regs)
 {
 	const u32 *data = (u32 *)regs->data;
 	int offset;
diff --git a/fec_8xx.c b/fec_8xx.c
index 69db8c8..02ecaef 100644
--- a/fec_8xx.c
+++ b/fec_8xx.c
@@ -47,7 +47,8 @@
 				(unsigned long)(offsetof(struct fec, x)), \
 				#x, f->x)
 
-int fec_8xx_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int fec_8xx_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		      struct ethtool_regs *regs)
 {
 	struct fec *f = (struct fec *)regs->data;
 
diff --git a/fjes.c b/fjes.c
index 52f7c28..4c5f6bc 100644
--- a/fjes.c
+++ b/fjes.c
@@ -2,7 +2,8 @@
 #include <stdio.h>
 #include "internal.h"
 
-int fjes_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int fjes_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		   struct ethtool_regs *regs)
 {
 	u32 *regs_buff = (u32 *)regs->data;
 
diff --git a/ibm_emac.c b/ibm_emac.c
index 75cb560..3259c17 100644
--- a/ibm_emac.c
+++ b/ibm_emac.c
@@ -314,7 +314,8 @@
 	return p + 1;
 }
 
-int ibm_emac_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int ibm_emac_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		       struct ethtool_regs *regs)
 {
 	struct emac_ethtool_regs_hdr *hdr =
 	    (struct emac_ethtool_regs_hdr *)regs->data;
diff --git a/igb.c b/igb.c
index e0ccef9..89b5cdb 100644
--- a/igb.c
+++ b/igb.c
@@ -88,8 +88,8 @@
 #define E1000_TCTL_RTLC   0x01000000    /* Re-transmit on late collision */
 #define E1000_TCTL_NRTU   0x02000000    /* No Re-transmit on underrun */
 
-int
-igb_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int igb_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		  struct ethtool_regs *regs)
 {
 	u32 *regs_buff = (u32 *)regs->data;
 	u32 reg;
@@ -859,6 +859,18 @@
 		"0x03430: TDFPC       (Tx data FIFO packet count)      0x%08X\n",
 		regs_buff[550]);
 
+	/*
+	 * Starting from kernel version 5.3 the registers dump buffer grew from
+	 * 739 4-byte words to 740 words, and word 740 contains the RR2DCDELAY
+	 * register.
+	 */
+	if (regs->len < 740)
+		return 0;
+
+	fprintf(stdout,
+		"0x05BF4: RR2DCDELAY  (Max. DMA read delay)            0x%08X\n",
+		regs_buff[739]);
+
 	return 0;
 }
 
diff --git a/internal.h b/internal.h
index aecf1ce..ff52c6e 100644
--- a/internal.h
+++ b/internal.h
@@ -23,6 +23,8 @@
 #include <sys/ioctl.h>
 #include <net/if.h>
 
+#define maybe_unused __attribute__((__unused__))
+
 /* ethtool.h expects these to be defined by <linux/types.h> */
 #ifndef HAVE_BE_TYPES
 typedef uint16_t __be16;
diff --git a/ixgb.c b/ixgb.c
index 8687c21..7c16c6e 100644
--- a/ixgb.c
+++ b/ixgb.c
@@ -38,8 +38,8 @@
 #define IXGB_RAH_ASEL_SRC         0x00010000
 #define IXGB_RAH_AV               0x80000000
 
-int
-ixgb_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int ixgb_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		   struct ethtool_regs *regs)
 {
 	u32 *regs_buff = (u32 *)regs->data;
 	u8 version = (u8)(regs->version >> 24);
diff --git a/ixgbe.c b/ixgbe.c
index 6779402..9754b2a 100644
--- a/ixgbe.c
+++ b/ixgbe.c
@@ -168,7 +168,8 @@
 }
 
 int
-ixgbe_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+ixgbe_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		struct ethtool_regs *regs)
 {
 	u32 *regs_buff = (u32 *)regs->data;
 	u32 regs_buff_len = regs->len / sizeof(*regs_buff);
diff --git a/ixgbevf.c b/ixgbevf.c
index 2a3aa6f..265e0bf 100644
--- a/ixgbevf.c
+++ b/ixgbevf.c
@@ -3,7 +3,8 @@
 #include "internal.h"
 
 int
-ixgbevf_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+ixgbevf_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		  struct ethtool_regs *regs)
 {
 	u32 *regs_buff = (u32 *)regs->data;
 	u8 version = (u8)(regs->version >> 24);
diff --git a/lan78xx.c b/lan78xx.c
index bb64e80..46ade1c 100644
--- a/lan78xx.c
+++ b/lan78xx.c
@@ -2,7 +2,8 @@
 #include <string.h>
 #include "internal.h"
 
-int lan78xx_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int lan78xx_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		      struct ethtool_regs *regs)
 {
 	unsigned int *lan78xx_reg = (unsigned int *)regs->data;
 
diff --git a/marvell.c b/marvell.c
index af21188..9e5440d 100644
--- a/marvell.c
+++ b/marvell.c
@@ -118,13 +118,13 @@
 	printf("\n%s\n", name);
 	printf("---------------\n");
 	printf("End Address                      0x%08X\n", r[0]);
-  	printf("Write Pointer                    0x%08X\n", r[1]);
-  	printf("Read Pointer                     0x%08X\n", r[2]);
-  	printf("Packet Counter                   0x%08X\n", r[3]);
-  	printf("Level                            0x%08X\n", r[4]);
-  	printf("Control                          0x%08X\n", r[5]);
-  	printf("Control/Test                     0x%08X\n", r[6]);
-	dump_timer("LED", p + 0x20);
+	printf("Write Pointer                    0x%08X\n", r[1]);
+	printf("Read Pointer                     0x%08X\n", r[2]);
+	printf("Packet Counter                   0x%08X\n", r[3]);
+	printf("Level                            0x%08X\n", r[4]);
+	printf("Control                          0x%08X\n", r[5]);
+	printf("Control/Test                     0x%08X\n", r[6]);
+	dump_timer("LED", r + 8);
 }
 
 static void dump_gmac_fifo(const char *name, const void *p)
@@ -259,7 +259,8 @@
 	printf("General Purpose  I/O             0x%08X\n", *(u32 *) (r + 0x15c));
 }
 
-int skge_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int skge_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		   struct ethtool_regs *regs)
 {
 	const u32 *r = (const u32 *) regs->data;
 	int dual = !(regs->data[0x11a] & 1);
@@ -379,7 +380,8 @@
 	}
 }
 
-int sky2_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int sky2_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		   struct ethtool_regs *regs)
 {
 	const u16 *r16 = (const u16 *) regs->data;
 	const u32 *r32 = (const u32 *) regs->data;
diff --git a/natsemi.c b/natsemi.c
index ac29be5..ce82c42 100644
--- a/natsemi.c
+++ b/natsemi.c
@@ -323,7 +323,8 @@
 } while (0)
 
 int
-natsemi_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+natsemi_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		  struct ethtool_regs *regs)
 {
 	u32 *data = (u32 *)regs->data;
 	u32 tmp;
@@ -963,7 +964,8 @@
 }
 
 int
-natsemi_dump_eeprom(struct ethtool_drvinfo *info, struct ethtool_eeprom *ee)
+natsemi_dump_eeprom(struct ethtool_drvinfo *info maybe_unused,
+		    struct ethtool_eeprom *ee)
 {
 	int i;
 	u16 *eebuf = (u16 *)ee->data;
diff --git a/realtek.c b/realtek.c
index e437466..d10cfd4 100644
--- a/realtek.c
+++ b/realtek.c
@@ -241,7 +241,8 @@
 }
 
 int
-realtek_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+realtek_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		  struct ethtool_regs *regs)
 {
 	u32 *data = (u32 *) regs->data;
 	u8 *data8 = (u8 *) regs->data;
diff --git a/sfc.c b/sfc.c
index b4c590f..f56243d 100644
--- a/sfc.c
+++ b/sfc.c
@@ -3808,8 +3808,7 @@
 }
 
 static const void *
-print_simple_table(unsigned revision, const struct efx_nic_reg_table *table,
-		   const void *buf)
+print_simple_table(const struct efx_nic_reg_table *table, const void *buf)
 {
 	const struct efx_nic_reg_field *field = &table->fields[0];
 	size_t value_width = (field->width + 3) >> 2;
@@ -3891,7 +3890,7 @@
 }
 
 int
-sfc_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+sfc_dump_regs(struct ethtool_drvinfo *info maybe_unused, struct ethtool_regs *regs)
 {
 	const struct efx_nic_reg *reg;
 	const struct efx_nic_reg_table *table;
@@ -3918,7 +3917,7 @@
 		    revision <= table->max_revision) {
 			printf("\n%s:\n", table->name);
 			if (table->field_count == 1)
-				buf = print_simple_table(revision, table, buf);
+				buf = print_simple_table(table, buf);
 			else
 				buf = print_complex_table(revision, table, buf);
 		}
diff --git a/smsc911x.c b/smsc911x.c
index c55b97b..bafee21 100644
--- a/smsc911x.c
+++ b/smsc911x.c
@@ -2,7 +2,8 @@
 #include <string.h>
 #include "internal.h"
 
-int smsc911x_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int smsc911x_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		       struct ethtool_regs *regs)
 {
 	unsigned int *smsc_reg = (unsigned int *)regs->data;
 
diff --git a/stmmac.c b/stmmac.c
index 79ef151..98d9058 100644
--- a/stmmac.c
+++ b/stmmac.c
@@ -18,7 +18,7 @@
 #define GMAC_REG_NUM		55
 #define GMAC_DMA_REG_NUM	23
 
-int st_mac100_dump_regs(struct ethtool_drvinfo *info,
+int st_mac100_dump_regs(struct ethtool_drvinfo *info maybe_unused,
 			struct ethtool_regs *regs)
 {
 	int i;
@@ -51,7 +51,8 @@
 	return 0;
 }
 
-int st_gmac_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int st_gmac_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		      struct ethtool_regs *regs)
 {
 	int i;
 	unsigned int *stmmac_reg = (unsigned int *)regs->data;
diff --git a/tg3.c b/tg3.c
index 3232339..8698391 100644
--- a/tg3.c
+++ b/tg3.c
@@ -4,8 +4,8 @@
 
 #define TG3_MAGIC 0x669955aa
 
-int
-tg3_dump_eeprom(struct ethtool_drvinfo *info, struct ethtool_eeprom *ee)
+int tg3_dump_eeprom(struct ethtool_drvinfo *info maybe_unused,
+		    struct ethtool_eeprom *ee)
 {
 	int i;
 
@@ -23,8 +23,8 @@
 	return 0;
 }
 
-int
-tg3_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int tg3_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		  struct ethtool_regs *regs)
 {
 	int i;
 	u32 reg;
diff --git a/tse.c b/tse.c
index f554dfe..e5241ee 100644
--- a/tse.c
+++ b/tse.c
@@ -25,7 +25,7 @@
 	return 0;
 }
 
-int altera_tse_dump_regs(struct ethtool_drvinfo *info,
+int altera_tse_dump_regs(struct ethtool_drvinfo *info maybe_unused,
 			 struct ethtool_regs *regs)
 {
 	int i;
diff --git a/vioc.c b/vioc.c
index eff533d..ef163ab 100644
--- a/vioc.c
+++ b/vioc.c
@@ -11,7 +11,8 @@
 
 #define VIOC_REGS_LINE_SIZE	sizeof(struct regs_line)
 
-int vioc_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+int vioc_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		   struct ethtool_regs *regs)
 {
 	unsigned int	i;
 	unsigned int	num_regs;
diff --git a/vmxnet3.c b/vmxnet3.c
index 621d02f..c972145 100644
--- a/vmxnet3.c
+++ b/vmxnet3.c
@@ -3,7 +3,8 @@
 #include "internal.h"
 
 int
-vmxnet3_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
+vmxnet3_dump_regs(struct ethtool_drvinfo *info maybe_unused,
+		  struct ethtool_regs *regs)
 {
 	u32 *regs_buff = (u32 *)regs->data;
 	u32 version = regs->version;