diff --git a/.ethtool.metadata b/.ethtool.metadata
index 7b43eeb..4ab498b 100644
--- a/.ethtool.metadata
+++ b/.ethtool.metadata
@@ -1 +1 @@
-cd71638cf3033dc83422b48a8c5e8831e6e05a84 SOURCES/ethtool-4.5.tar.xz
+db82313f212aa1e1b8f5f892f25a9883bea26b9f SOURCES/ethtool-4.8.tar.xz
diff --git a/.gitignore b/.gitignore
index 135bc2d..8a95788 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/ethtool-4.5.tar.xz
+SOURCES/ethtool-4.8.tar.xz
diff --git a/SOURCES/0001-ethtool-add-register-dump-support-for-fjes-driver.patch b/SOURCES/0001-ethtool-add-register-dump-support-for-fjes-driver.patch
new file mode 100644
index 0000000..c0010e4
--- /dev/null
+++ b/SOURCES/0001-ethtool-add-register-dump-support-for-fjes-driver.patch
@@ -0,0 +1,174 @@
+From 1be465a88eb247b78ddbc3129f53cc547ce8687b Mon Sep 17 00:00:00 2001
+From: Taku Izumi <izumi.taku@jp.fujitsu.com>
+Date: Wed, 16 Nov 2016 09:55:32 +0900
+Subject: [PATCH 1/3] ethtool: add register dump support for fjes driver
+
+This patch adds the register dump format for FUJITSU Extended
+Network device like the following:
+
+   # ethtool -d es0
+
+0x0000: OWNER_EPID    (Owner EPID)                       0x00000001
+0x0004: MAX_EP        (Maximum EP)                       0x00000008
+0x0010: DCTL          (Device Control)                   0x00000000
+0x0020: CR            (Command request)                  0x80000002
+0x0024: CS            (Command status)                   0x80000002
+0x0028: SHSTSAL       (Share status address Low)         0xE8215304
+0x002C: SHSTSAH       (Share status address High)        0x00000007
+0x0034: REQBL         (Request Buffer length)            0x00008028
+0x0038: REQBAL        (Request Buffer Address Low)       0xEB0A0000
+0x003C: REQBAH        (Request Buffer Address High)      0x00000007
+0x0044: RESPBL        (Response Buffer Length)           0x00000018
+0x0048: RESPBAL       (Response Buffer Address Low)      0xE41E1220
+0x004C: RESPBAH       (Response Buffer Address High)     0x00000007
+0x0080: IS            (Interrupt status)                 0x00000000
+0x0084: IMS           (Interrupt mask set)               0x7FE00000
+0x0088: IMC           (Interrupt mask clear)             0x001F0000
+0x008C: IG            (Interrupt generator)              0x00010000
+0x0090: ICTL          (Interrupt control)                0x00000000
+
+Signed-off-by: Taku Izumi <izumi.taku@jp.fujitsu.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+(cherry picked from commit acc3d3a32940cdd3325520d212fa94f44b86ed09)
+---
+ Makefile.am |  2 +-
+ ethtool.c   |  1 +
+ fjes.c      | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ internal.h  |  2 ++
+ 4 files changed, 93 insertions(+), 1 deletion(-)
+ create mode 100644 fjes.c
+
+diff --git a/Makefile.am b/Makefile.am
+index de2db2e..edbda57 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -14,7 +14,7 @@ ethtool_SOURCES += \
+ 		  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
++		  ixgbevf.c tse.c vmxnet3.c qsfp.c qsfp.h fjes.c
+ endif
+ 
+ TESTS = test-cmdline test-features
+diff --git a/ethtool.c b/ethtool.c
+index 49ac94e..75299c6 100644
+--- a/ethtool.c
++++ b/ethtool.c
+@@ -1136,6 +1136,7 @@ static const struct {
+ 	{ "et131x", et131x_dump_regs },
+ 	{ "altera_tse", altera_tse_dump_regs },
+ 	{ "vmxnet3", vmxnet3_dump_regs },
++	{ "fjes", fjes_dump_regs },
+ #endif
+ };
+ 
+diff --git a/fjes.c b/fjes.c
+new file mode 100644
+index 0000000..52f7c28
+--- /dev/null
++++ b/fjes.c
+@@ -0,0 +1,89 @@
++/* Copyright (c) 2016 FUJITSU LIMITED */
++#include <stdio.h>
++#include "internal.h"
++
++int fjes_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
++{
++	u32 *regs_buff = (u32 *)regs->data;
++
++	if (regs->version != 1)
++		return -1;
++
++	/* Information registers */
++	fprintf(stdout,
++		"0x0000: OWNER_EPID    (Owner EPID)                       0x%08X\n",
++		regs_buff[0]);
++
++	fprintf(stdout,
++		"0x0004: MAX_EP        (Maximum EP)                       0x%08X\n",
++		regs_buff[1]);
++
++	/* Device Control registers */
++	fprintf(stdout,
++		"0x0010: DCTL          (Device Control)                   0x%08X\n",
++		regs_buff[4]);
++
++	/* Command Control registers */
++	fprintf(stdout,
++		"0x0020: CR            (Command request)                  0x%08X\n",
++		regs_buff[8]);
++
++	fprintf(stdout,
++		"0x0024: CS            (Command status)                   0x%08X\n",
++		regs_buff[9]);
++
++	fprintf(stdout,
++		"0x0028: SHSTSAL       (Share status address Low)         0x%08X\n",
++		regs_buff[10]);
++
++	fprintf(stdout,
++		"0x002C: SHSTSAH       (Share status address High)        0x%08X\n",
++		regs_buff[11]);
++
++	fprintf(stdout,
++		"0x0034: REQBL         (Request Buffer length)            0x%08X\n",
++		regs_buff[13]);
++
++	fprintf(stdout,
++		"0x0038: REQBAL        (Request Buffer Address Low)       0x%08X\n",
++		regs_buff[14]);
++
++	fprintf(stdout,
++		"0x003C: REQBAH        (Request Buffer Address High)      0x%08X\n",
++		regs_buff[15]);
++
++	fprintf(stdout,
++		"0x0044: RESPBL        (Response Buffer Length)           0x%08X\n",
++		regs_buff[17]);
++
++	fprintf(stdout,
++		"0x0048: RESPBAL       (Response Buffer Address Low)      0x%08X\n",
++		regs_buff[18]);
++
++	fprintf(stdout,
++		"0x004C: RESPBAH       (Response Buffer Address High)     0x%08X\n",
++		regs_buff[19]);
++
++	/* Interrupt Control registers */
++	fprintf(stdout,
++		"0x0080: IS            (Interrupt status)                 0x%08X\n",
++		regs_buff[32]);
++
++	fprintf(stdout,
++		"0x0084: IMS           (Interrupt mask set)               0x%08X\n",
++		regs_buff[33]);
++
++	fprintf(stdout,
++		"0x0088: IMC           (Interrupt mask clear)             0x%08X\n",
++		regs_buff[34]);
++
++	fprintf(stdout,
++		"0x008C: IG            (Interrupt generator)              0x%08X\n",
++		regs_buff[35]);
++
++	fprintf(stdout,
++		"0x0090: ICTL          (Interrupt control)                0x%08X\n",
++		regs_buff[36]);
++
++	return 0;
++}
+diff --git a/internal.h b/internal.h
+index 3c08b74..4e658ea 100644
+--- a/internal.h
++++ b/internal.h
+@@ -348,4 +348,6 @@ void sff8472_show_all(const __u8 *id);
+ /* QSFP Optics diagnostics */
+ void sff8636_show_all(const __u8 *id, __u32 eeprom_len);
+ 
++/* FUJITSU Extended Socket network device */
++int fjes_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
+ #endif /* ETHTOOL_INTERNAL_H__ */
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0001-ethtool.c-fix-memory-leaks.patch b/SOURCES/0001-ethtool.c-fix-memory-leaks.patch
deleted file mode 100644
index b592b31..0000000
--- a/SOURCES/0001-ethtool.c-fix-memory-leaks.patch
+++ /dev/null
@@ -1,223 +0,0 @@
-From 266d945d9c6432fc5746fa46e3e3ace2518600db Mon Sep 17 00:00:00 2001
-From: Ivan Vecera <ivecera@redhat.com>
-Date: Fri, 18 Mar 2016 12:50:43 +0100
-Subject: [PATCH] ethtool.c: fix memory leaks
-
-Memory allocated at several places is not appropriately freed.
-
-Signed-off-by: Ivan Vecera <ivecera@redhat.com>
----
- ethtool.c | 60 +++++++++++++++++++++++++++++++++++++++++++++---------------
- 1 file changed, 45 insertions(+), 15 deletions(-)
-
-diff --git a/ethtool.c b/ethtool.c
-index 0cd0d4f..ca0bf28 100644
---- a/ethtool.c
-+++ b/ethtool.c
-@@ -2065,10 +2065,14 @@ static int do_gfeatures(struct cmd_context *ctx)
- 	features = get_features(ctx, defs);
- 	if (!features) {
- 		fprintf(stdout, "no feature info available\n");
-+		free(defs);
- 		return 1;
- 	}
- 
- 	dump_features(defs, features, NULL);
-+
-+	free(features);
-+	free(defs);
- 	return 0;
- }
- 
-@@ -2078,11 +2082,11 @@ static int do_sfeatures(struct cmd_context *ctx)
- 	int any_changed = 0, any_mismatch = 0;
- 	u32 off_flags_wanted = 0;
- 	u32 off_flags_mask = 0;
--	struct ethtool_sfeatures *efeatures;
-+	struct ethtool_sfeatures *efeatures = NULL;
- 	struct cmdline_info *cmdline_features;
--	struct feature_state *old_state, *new_state;
-+	struct feature_state *old_state = NULL, *new_state = NULL;
- 	struct ethtool_value eval;
--	int err;
-+	int err, retval = 1;
- 	int i, j;
- 
- 	defs = get_feature_defs(ctx);
-@@ -2096,7 +2100,7 @@ static int do_sfeatures(struct cmd_context *ctx)
- 				   sizeof(efeatures->features[0]));
- 		if (!efeatures) {
- 			perror("Cannot parse arguments");
--			return 1;
-+			goto finish;
- 		}
- 		efeatures->cmd = ETHTOOL_SFEATURES;
- 		efeatures->size = FEATURE_BITS_TO_BLOCKS(defs->n_features);
-@@ -2114,7 +2118,7 @@ static int do_sfeatures(struct cmd_context *ctx)
- 				  sizeof(cmdline_features[0]));
- 	if (!cmdline_features) {
- 		perror("Cannot parse arguments");
--		return 1;
-+		goto finish;
- 	}
- 	for (i = 0; i < ARRAY_SIZE(off_flag_def); i++)
- 		flag_to_cmdline_info(off_flag_def[i].short_name,
-@@ -2133,12 +2137,13 @@ static int do_sfeatures(struct cmd_context *ctx)
- 
- 	if (!any_changed) {
- 		fprintf(stdout, "no features changed\n");
--		return 0;
-+		retval = 0;
-+		goto finish;
- 	}
- 
- 	old_state = get_features(ctx, defs);
- 	if (!old_state)
--		return 1;
-+		goto finish;
- 
- 	if (efeatures) {
- 		/* For each offload that the user specified, update any
-@@ -2182,7 +2187,7 @@ static int do_sfeatures(struct cmd_context *ctx)
- 		err = send_ioctl(ctx, efeatures);
- 		if (err < 0) {
- 			perror("Cannot set device feature settings");
--			return 1;
-+			goto finish;
- 		}
- 	} else {
- 		for (i = 0; i < ARRAY_SIZE(off_flag_def); i++) {
-@@ -2197,7 +2202,7 @@ static int do_sfeatures(struct cmd_context *ctx)
- 					fprintf(stderr,
- 						"Cannot set device %s settings: %m\n",
- 						off_flag_def[i].long_name);
--					return 1;
-+					goto finish;
- 				}
- 			}
- 		}
-@@ -2211,7 +2216,8 @@ static int do_sfeatures(struct cmd_context *ctx)
- 			err = send_ioctl(ctx, &eval);
- 			if (err) {
- 				perror("Cannot set device flag settings");
--				return 92;
-+				retval = 92;
-+				goto finish;
- 			}
- 		}
- 	}
-@@ -2219,7 +2225,7 @@ static int do_sfeatures(struct cmd_context *ctx)
- 	/* Compare new state with requested state */
- 	new_state = get_features(ctx, defs);
- 	if (!new_state)
--		return 1;
-+		goto finish;
- 	any_changed = new_state->off_flags != old_state->off_flags;
- 	any_mismatch = (new_state->off_flags !=
- 			((old_state->off_flags & ~off_flags_mask) |
-@@ -2238,13 +2244,19 @@ static int do_sfeatures(struct cmd_context *ctx)
- 		if (!any_changed) {
- 			fprintf(stderr,
- 				"Could not change any device features\n");
--			return 1;
-+			goto finish;
- 		}
- 		printf("Actual changes:\n");
- 		dump_features(defs, new_state, old_state);
- 	}
- 
--	return 0;
-+	retval = 0;
-+finish:
-+	free(new_state);
-+	free(old_state);
-+	free(efeatures);
-+	free(defs);
-+	return retval;
- }
- 
- static int do_gset(struct cmd_context *ctx)
-@@ -2705,8 +2717,18 @@ static int do_gregs(struct cmd_context *ctx)
- 			return 75;
- 		}
- 
--		regs = realloc(regs, sizeof(*regs) + st.st_size);
--		regs->len = st.st_size;
-+		if (regs->len != st.st_size) {
-+			struct ethtool_regs *new_regs;
-+			new_regs = realloc(regs, sizeof(*regs) + st.st_size);
-+			if (!new_regs) {
-+				perror("Cannot allocate memory for register "
-+				       "dump");
-+				free(regs);
-+				return 73;
-+			}
-+			regs = new_regs;
-+			regs->len = st.st_size;
-+		}
- 		nread = fread(regs->data, regs->len, 1, f);
- 		fclose(f);
- 		if (nread != 1) {
-@@ -3775,6 +3797,7 @@ static int do_gprivflags(struct cmd_context *ctx)
- 	}
- 	if (strings->len == 0) {
- 		fprintf(stderr, "No private flags defined\n");
-+		free(strings);
- 		return 1;
- 	}
- 	if (strings->len > 32) {
-@@ -3786,6 +3809,7 @@ static int do_gprivflags(struct cmd_context *ctx)
- 	flags.cmd = ETHTOOL_GPFLAGS;
- 	if (send_ioctl(ctx, &flags)) {
- 		perror("Cannot get private flags");
-+		free(strings);
- 		return 1;
- 	}
- 
-@@ -3804,6 +3828,7 @@ static int do_gprivflags(struct cmd_context *ctx)
- 		       (const char *)strings->data + i * ETH_GSTRING_LEN,
- 		       (flags.data & (1U << i)) ? "on" : "off");
- 
-+	free(strings);
- 	return 0;
- }
- 
-@@ -3825,6 +3850,7 @@ static int do_sprivflags(struct cmd_context *ctx)
- 	}
- 	if (strings->len == 0) {
- 		fprintf(stderr, "No private flags defined\n");
-+		free(strings);
- 		return 1;
- 	}
- 	if (strings->len > 32) {
-@@ -3836,6 +3862,7 @@ static int do_sprivflags(struct cmd_context *ctx)
- 	cmdline = calloc(strings->len, sizeof(*cmdline));
- 	if (!cmdline) {
- 		perror("Cannot parse arguments");
-+		free(strings);
- 		return 1;
- 	}
- 	for (i = 0; i < strings->len; i++) {
-@@ -3852,6 +3879,7 @@ static int do_sprivflags(struct cmd_context *ctx)
- 	flags.cmd = ETHTOOL_GPFLAGS;
- 	if (send_ioctl(ctx, &flags)) {
- 		perror("Cannot get private flags");
-+		free(strings);
- 		return 1;
- 	}
- 
-@@ -3859,9 +3887,11 @@ static int do_sprivflags(struct cmd_context *ctx)
- 	flags.data = (flags.data & ~seen_flags) | wanted_flags;
- 	if (send_ioctl(ctx, &flags)) {
- 		perror("Cannot set private flags");
-+		free(strings);
- 		return 1;
- 	}
- 
-+	free(strings);
- 	return 0;
- }
- 
--- 
-2.7.3
-
diff --git a/SOURCES/0002-ethtool-sync-help-output-for-x-X-with-man-page.patch b/SOURCES/0002-ethtool-sync-help-output-for-x-X-with-man-page.patch
new file mode 100644
index 0000000..17cb755
--- /dev/null
+++ b/SOURCES/0002-ethtool-sync-help-output-for-x-X-with-man-page.patch
@@ -0,0 +1,34 @@
+From d695f60666453d964a653c5033764c4b80121f56 Mon Sep 17 00:00:00 2001
+From: Ivan Vecera <cera@cera.cz>
+Date: Mon, 20 Feb 2017 15:13:52 +0100
+Subject: [PATCH 2/3] ethtool: sync help output for -x/-X with man page
+
+Add missing words to the help output for -x and -X commands as well
+as an ability to set the indirection table to default value.
+
+Signed-off-by: Ivan Vecera <cera@cera.cz>
+---
+ ethtool.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/ethtool.c b/ethtool.c
+index 75299c6..0d3244e 100644
+--- a/ethtool.c
++++ b/ethtool.c
+@@ -4645,10 +4645,10 @@ static const struct option {
+ 	{ "-T|--show-time-stamping", 1, do_tsinfo,
+ 	  "Show time stamping capabilities" },
+ 	{ "-x|--show-rxfh-indir|--show-rxfh", 1, do_grxfh,
+-	  "Show Rx flow hash indirection and/or hash key" },
++	  "Show Rx flow hash indirection table and/or RSS hash key" },
+ 	{ "-X|--set-rxfh-indir|--rxfh", 1, do_srxfh,
+-	  "Set Rx flow hash indirection and/or hash key",
+-	  "		[ equal N | weight W0 W1 ... ]\n"
++	  "Set Rx flow hash indirection table and/or RSS hash key",
++	  "		[ equal N | weight W0 W1 ... | default ]\n"
+ 	  "		[ hkey %x:%x:%x:%x:%x:.... ]\n" },
+ 	{ "-f|--flash", 1, do_flash,
+ 	  "Flash firmware image from the specified file to a region on the device",
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0002-ethtool.c-add-support-for-ETHTOOL_xLINKSETTINGS-ioctl.patch b/SOURCES/0002-ethtool.c-add-support-for-ETHTOOL_xLINKSETTINGS-ioctl.patch
deleted file mode 100644
index 10392c4..0000000
--- a/SOURCES/0002-ethtool.c-add-support-for-ETHTOOL_xLINKSETTINGS-ioctl.patch
+++ /dev/null
@@ -1,1072 +0,0 @@
-From 00a31b21a767be682a27d631a7c9df2a41c41e06 Mon Sep 17 00:00:00 2001
-From: David Decotigny <decot@googlers.com>
-Date: Fri, 25 Mar 2016 09:21:01 -0700
-Subject: [PATCH 2/7] ethtool.c: add support for ETHTOOL_xLINKSETTINGS ioctls
-
-More info with kernel commit 8d3f2806f8fb ("Merge branch
-'ethtool-ksettings'").
-
-Note: The new features implemented in this patch depend on kernel
-commit 793cf87de9d1 ("Set cmd field in ETHTOOL_GLINKSETTINGS response to
-wrong nwords").
-
-Signed-off-by: David Decotigny <decot@googlers.com>
-[bwh: Fix style:
- - Remove '_' and '__' prefixes from newly defined names
- - Add space around multiplication operator
- - Remove space before semi-colon]
-Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-
-(cherry picked from commit 33133abf3b777a2e0730f826817c8e05b3616150)
----
- ethtool.c      | 680 +++++++++++++++++++++++++++++++++++++++++++--------------
- internal.h     |  66 ++++++
- test-cmdline.c |  13 ++
- 3 files changed, 601 insertions(+), 158 deletions(-)
-
-diff --git a/ethtool.c b/ethtool.c
-index ca0bf28..796d0b5 100644
---- a/ethtool.c
-+++ b/ethtool.c
-@@ -47,42 +47,6 @@
- #define MAX_ADDR_LEN	32
- #endif
- 
--#define ALL_ADVERTISED_MODES			\
--	(ADVERTISED_10baseT_Half |		\
--	 ADVERTISED_10baseT_Full |		\
--	 ADVERTISED_100baseT_Half |		\
--	 ADVERTISED_100baseT_Full |		\
--	 ADVERTISED_1000baseT_Half |		\
--	 ADVERTISED_1000baseT_Full |		\
--	 ADVERTISED_1000baseKX_Full|		\
--	 ADVERTISED_2500baseX_Full |		\
--	 ADVERTISED_10000baseT_Full |		\
--	 ADVERTISED_10000baseKX4_Full |		\
--	 ADVERTISED_10000baseKR_Full |		\
--	 ADVERTISED_10000baseR_FEC |		\
--	 ADVERTISED_20000baseMLD2_Full |	\
--	 ADVERTISED_20000baseKR2_Full |		\
--	 ADVERTISED_40000baseKR4_Full |		\
--	 ADVERTISED_40000baseCR4_Full |		\
--	 ADVERTISED_40000baseSR4_Full |		\
--	 ADVERTISED_40000baseLR4_Full |		\
--	 ADVERTISED_56000baseKR4_Full |		\
--	 ADVERTISED_56000baseCR4_Full |		\
--	 ADVERTISED_56000baseSR4_Full |		\
--	 ADVERTISED_56000baseLR4_Full)
--
--#define ALL_ADVERTISED_FLAGS			\
--	(ADVERTISED_Autoneg |			\
--	 ADVERTISED_TP |			\
--	 ADVERTISED_AUI |			\
--	 ADVERTISED_MII |			\
--	 ADVERTISED_FIBRE |			\
--	 ADVERTISED_BNC |			\
--	 ADVERTISED_Pause |			\
--	 ADVERTISED_Asym_Pause |		\
--	 ADVERTISED_Backplane |			\
--	 ALL_ADVERTISED_MODES)
--
- #ifndef HAVE_NETIF_MSG
- enum {
- 	NETIF_MSG_DRV		= 0x0001,
-@@ -293,6 +257,43 @@ static void get_mac_addr(char *src, unsigned char *dest)
- 	}
- }
- 
-+static int parse_hex_u32_bitmap(const char *s,
-+				unsigned int nbits, u32 *result)
-+{
-+	const unsigned int nwords = __KERNEL_DIV_ROUND_UP(nbits, 32);
-+	size_t slen = strlen(s);
-+	size_t i;
-+
-+	/* ignore optional '0x' prefix */
-+	if ((slen > 2) && (strncasecmp(s, "0x", 2) == 0)) {
-+		slen -= 2;
-+		s += 2;
-+	}
-+
-+	if (slen > 8 * nwords)  /* up to 2 digits per byte */
-+		return -1;
-+
-+	memset(result, 0, 4 * nwords);
-+	for (i = 0; i < slen; ++i) {
-+		const unsigned int shift = (slen - 1 - i) * 4;
-+		u32 *dest = &result[shift / 32];
-+		u32 nibble;
-+
-+		if ('a' <= s[i] && s[i] <= 'f')
-+			nibble = 0xa + (s[i] - 'a');
-+		else if ('A' <= s[i] && s[i] <= 'F')
-+			nibble = 0xa + (s[i] - 'A');
-+		else if ('0' <= s[i] && s[i] <= '9')
-+			nibble = (s[i] - '0');
-+		else
-+			return -1;
-+
-+		*dest |= (nibble << (shift % 32));
-+	}
-+
-+	return 0;
-+}
-+
- static void parse_generic_cmdline(struct cmd_context *ctx,
- 				  int *changed,
- 				  struct cmdline_info *info,
-@@ -472,64 +473,157 @@ static int do_version(struct cmd_context *ctx)
- 	return 0;
- }
- 
--static void dump_link_caps(const char *prefix, const char *an_prefix, u32 mask,
--			   int link_mode_only);
-+/* link mode routines */
- 
--static void dump_supported(struct ethtool_cmd *ep)
-+static ETHTOOL_DECLARE_LINK_MODE_MASK(all_advertised_modes);
-+static ETHTOOL_DECLARE_LINK_MODE_MASK(all_advertised_flags);
-+
-+static void init_global_link_mode_masks(void)
- {
--	u32 mask = ep->supported;
-+	static const enum ethtool_link_mode_bit_indices
-+		all_advertised_modes_bits[] = {
-+		ETHTOOL_LINK_MODE_10baseT_Half_BIT,
-+		ETHTOOL_LINK_MODE_10baseT_Full_BIT,
-+		ETHTOOL_LINK_MODE_100baseT_Half_BIT,
-+		ETHTOOL_LINK_MODE_100baseT_Full_BIT,
-+		ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
-+		ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
-+		ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
-+		ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
-+		ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
-+		ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
-+		ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
-+		ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
-+		ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT,
-+		ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
-+		ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
-+		ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
-+		ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
-+		ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
-+		ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT,
-+		ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT,
-+		ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT,
-+		ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
-+	};
-+	static const enum ethtool_link_mode_bit_indices
-+		additional_advertised_flags_bits[] = {
-+		ETHTOOL_LINK_MODE_Autoneg_BIT,
-+		ETHTOOL_LINK_MODE_TP_BIT,
-+		ETHTOOL_LINK_MODE_AUI_BIT,
-+		ETHTOOL_LINK_MODE_MII_BIT,
-+		ETHTOOL_LINK_MODE_FIBRE_BIT,
-+		ETHTOOL_LINK_MODE_BNC_BIT,
-+		ETHTOOL_LINK_MODE_Pause_BIT,
-+		ETHTOOL_LINK_MODE_Asym_Pause_BIT,
-+		ETHTOOL_LINK_MODE_Backplane_BIT,
-+	};
-+	unsigned int i;
- 
-+	ethtool_link_mode_zero(all_advertised_modes);
-+	ethtool_link_mode_zero(all_advertised_flags);
-+	for (i = 0; i < ARRAY_SIZE(all_advertised_modes_bits); ++i) {
-+		ethtool_link_mode_set_bit(all_advertised_modes_bits[i],
-+					  all_advertised_modes);
-+		ethtool_link_mode_set_bit(all_advertised_modes_bits[i],
-+					  all_advertised_flags);
-+	}
-+
-+	for (i = 0; i < ARRAY_SIZE(additional_advertised_flags_bits); ++i) {
-+		ethtool_link_mode_set_bit(
-+			additional_advertised_flags_bits[i],
-+			all_advertised_flags);
-+	}
-+}
-+
-+static void dump_link_caps(const char *prefix, const char *an_prefix,
-+			   const u32 *mask, int link_mode_only);
-+
-+static void dump_supported(const struct ethtool_link_usettings *link_usettings)
-+{
- 	fprintf(stdout, "	Supported ports: [ ");
--	if (mask & SUPPORTED_TP)
-+	if (ethtool_link_mode_test_bit(
-+		    ETHTOOL_LINK_MODE_TP_BIT,
-+		    link_usettings->link_modes.supported))
- 		fprintf(stdout, "TP ");
--	if (mask & SUPPORTED_AUI)
-+	if (ethtool_link_mode_test_bit(
-+		    ETHTOOL_LINK_MODE_AUI_BIT,
-+		    link_usettings->link_modes.supported))
- 		fprintf(stdout, "AUI ");
--	if (mask & SUPPORTED_BNC)
-+	if (ethtool_link_mode_test_bit(
-+		    ETHTOOL_LINK_MODE_BNC_BIT,
-+		    link_usettings->link_modes.supported))
- 		fprintf(stdout, "BNC ");
--	if (mask & SUPPORTED_MII)
-+	if (ethtool_link_mode_test_bit(
-+		    ETHTOOL_LINK_MODE_MII_BIT,
-+		    link_usettings->link_modes.supported))
- 		fprintf(stdout, "MII ");
--	if (mask & SUPPORTED_FIBRE)
-+	if (ethtool_link_mode_test_bit(
-+		    ETHTOOL_LINK_MODE_FIBRE_BIT,
-+		    link_usettings->link_modes.supported))
- 		fprintf(stdout, "FIBRE ");
--	if (mask & SUPPORTED_Backplane)
-+	if (ethtool_link_mode_test_bit(
-+		    ETHTOOL_LINK_MODE_Backplane_BIT,
-+		    link_usettings->link_modes.supported))
- 		fprintf(stdout, "Backplane ");
- 	fprintf(stdout, "]\n");
- 
--	dump_link_caps("Supported", "Supports", mask, 0);
-+	dump_link_caps("Supported", "Supports",
-+		       link_usettings->link_modes.supported, 0);
- }
- 
- /* Print link capability flags (supported, advertised or lp_advertised).
-  * Assumes that the corresponding SUPPORTED and ADVERTISED flags are equal.
-  */
--static void
--dump_link_caps(const char *prefix, const char *an_prefix, u32 mask,
--	       int link_mode_only)
-+static void dump_link_caps(const char *prefix, const char *an_prefix,
-+			   const u32 *mask, int link_mode_only)
- {
- 	static const struct {
- 		int same_line; /* print on same line as previous */
--		u32 value;
-+		unsigned int bit_index;
- 		const char *name;
- 	} mode_defs[] = {
--		{ 0, ADVERTISED_10baseT_Half,       "10baseT/Half" },
--		{ 1, ADVERTISED_10baseT_Full,       "10baseT/Full" },
--		{ 0, ADVERTISED_100baseT_Half,      "100baseT/Half" },
--		{ 1, ADVERTISED_100baseT_Full,      "100baseT/Full" },
--		{ 0, ADVERTISED_1000baseT_Half,     "1000baseT/Half" },
--		{ 1, ADVERTISED_1000baseT_Full,     "1000baseT/Full" },
--		{ 0, ADVERTISED_1000baseKX_Full,    "1000baseKX/Full" },
--		{ 0, ADVERTISED_2500baseX_Full,     "2500baseX/Full" },
--		{ 0, ADVERTISED_10000baseT_Full,    "10000baseT/Full" },
--		{ 0, ADVERTISED_10000baseKX4_Full,  "10000baseKX4/Full" },
--		{ 0, ADVERTISED_10000baseKR_Full,   "10000baseKR/Full" },
--		{ 0, ADVERTISED_20000baseMLD2_Full, "20000baseMLD2/Full" },
--		{ 0, ADVERTISED_20000baseKR2_Full,  "20000baseKR2/Full" },
--		{ 0, ADVERTISED_40000baseKR4_Full,  "40000baseKR4/Full" },
--		{ 0, ADVERTISED_40000baseCR4_Full,  "40000baseCR4/Full" },
--		{ 0, ADVERTISED_40000baseSR4_Full,  "40000baseSR4/Full" },
--		{ 0, ADVERTISED_40000baseLR4_Full,  "40000baseLR4/Full" },
--		{ 0, ADVERTISED_56000baseKR4_Full,  "56000baseKR4/Full" },
--		{ 0, ADVERTISED_56000baseCR4_Full,  "56000baseCR4/Full" },
--		{ 0, ADVERTISED_56000baseSR4_Full,  "56000baseSR4/Full" },
--		{ 0, ADVERTISED_56000baseLR4_Full,  "56000baseLR4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_10baseT_Half_BIT,
-+		  "10baseT/Half" },
-+		{ 1, ETHTOOL_LINK_MODE_10baseT_Full_BIT,
-+		  "10baseT/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_100baseT_Half_BIT,
-+		  "100baseT/Half" },
-+		{ 1, ETHTOOL_LINK_MODE_100baseT_Full_BIT,
-+		  "100baseT/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
-+		  "1000baseT/Half" },
-+		{ 1, ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
-+		  "1000baseT/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
-+		  "1000baseKX/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
-+		  "2500baseX/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
-+		  "10000baseT/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
-+		  "10000baseKX4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
-+		  "10000baseKR/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT,
-+		  "20000baseMLD2/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
-+		  "20000baseKR2/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
-+		  "40000baseKR4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
-+		  "40000baseCR4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
-+		  "40000baseSR4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
-+		  "40000baseLR4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT,
-+		  "56000baseKR4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT,
-+		  "56000baseCR4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT,
-+		  "56000baseSR4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
-+		  "56000baseLR4/Full" },
- 	};
- 	int indent;
- 	int did1, new_line_pend, i;
-@@ -546,7 +640,8 @@ dump_link_caps(const char *prefix, const char *an_prefix, u32 mask,
- 	for (i = 0; i < ARRAY_SIZE(mode_defs); i++) {
- 		if (did1 && !mode_defs[i].same_line)
- 			new_line_pend = 1;
--		if (mask & mode_defs[i].value) {
-+		if (ethtool_link_mode_test_bit(mode_defs[i].bit_index,
-+					       mask)) {
- 			if (new_line_pend) {
- 				fprintf(stdout, "\n");
- 				fprintf(stdout, "	%*s", indent, "");
-@@ -562,46 +657,52 @@ dump_link_caps(const char *prefix, const char *an_prefix, u32 mask,
- 
- 	if (!link_mode_only) {
- 		fprintf(stdout, "	%s pause frame use: ", prefix);
--		if (mask & ADVERTISED_Pause) {
-+		if (ethtool_link_mode_test_bit(
-+			    ETHTOOL_LINK_MODE_Pause_BIT, mask)) {
- 			fprintf(stdout, "Symmetric");
--			if (mask & ADVERTISED_Asym_Pause)
-+			if (ethtool_link_mode_test_bit(
-+				    ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask))
- 				fprintf(stdout, " Receive-only");
- 			fprintf(stdout, "\n");
- 		} else {
--			if (mask & ADVERTISED_Asym_Pause)
-+			if (ethtool_link_mode_test_bit(
-+				    ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask))
- 				fprintf(stdout, "Transmit-only\n");
- 			else
- 				fprintf(stdout, "No\n");
- 		}
- 
- 		fprintf(stdout, "	%s auto-negotiation: ", an_prefix);
--		if (mask & ADVERTISED_Autoneg)
-+		if (ethtool_link_mode_test_bit(
-+			    ETHTOOL_LINK_MODE_Autoneg_BIT, mask))
- 			fprintf(stdout, "Yes\n");
- 		else
- 			fprintf(stdout, "No\n");
- 	}
- }
- 
--static int dump_ecmd(struct ethtool_cmd *ep)
-+static int
-+dump_link_usettings(const struct ethtool_link_usettings *link_usettings)
- {
--	u32 speed;
--
--	dump_supported(ep);
--	dump_link_caps("Advertised", "Advertised", ep->advertising, 0);
--	if (ep->lp_advertising)
-+	dump_supported(link_usettings);
-+	dump_link_caps("Advertised", "Advertised",
-+		       link_usettings->link_modes.advertising, 0);
-+	if (!ethtool_link_mode_is_empty(
-+		    link_usettings->link_modes.lp_advertising))
- 		dump_link_caps("Link partner advertised",
--			       "Link partner advertised", ep->lp_advertising,
--			       0);
-+			       "Link partner advertised",
-+			       link_usettings->link_modes.lp_advertising, 0);
- 
- 	fprintf(stdout, "	Speed: ");
--	speed = ethtool_cmd_speed(ep);
--	if (speed == 0 || speed == (u16)(-1) || speed == (u32)(-1))
-+	if (link_usettings->base.speed == 0
-+	    || link_usettings->base.speed == (u16)(-1)
-+	    || link_usettings->base.speed == (u32)(-1))
- 		fprintf(stdout, "Unknown!\n");
- 	else
--		fprintf(stdout, "%uMb/s\n", speed);
-+		fprintf(stdout, "%uMb/s\n", link_usettings->base.speed);
- 
- 	fprintf(stdout, "	Duplex: ");
--	switch (ep->duplex) {
-+	switch (link_usettings->base.duplex) {
- 	case DUPLEX_HALF:
- 		fprintf(stdout, "Half\n");
- 		break;
-@@ -609,12 +710,12 @@ static int dump_ecmd(struct ethtool_cmd *ep)
- 		fprintf(stdout, "Full\n");
- 		break;
- 	default:
--		fprintf(stdout, "Unknown! (%i)\n", ep->duplex);
-+		fprintf(stdout, "Unknown! (%i)\n", link_usettings->base.duplex);
- 		break;
- 	};
- 
- 	fprintf(stdout, "	Port: ");
--	switch (ep->port) {
-+	switch (link_usettings->base.port) {
- 	case PORT_TP:
- 		fprintf(stdout, "Twisted Pair\n");
- 		break;
-@@ -640,13 +741,13 @@ static int dump_ecmd(struct ethtool_cmd *ep)
- 		fprintf(stdout, "Other\n");
- 		break;
- 	default:
--		fprintf(stdout, "Unknown! (%i)\n", ep->port);
-+		fprintf(stdout, "Unknown! (%i)\n", link_usettings->base.port);
- 		break;
- 	};
- 
--	fprintf(stdout, "	PHYAD: %d\n", ep->phy_address);
-+	fprintf(stdout, "	PHYAD: %d\n", link_usettings->base.phy_address);
- 	fprintf(stdout, "	Transceiver: ");
--	switch (ep->transceiver) {
-+	switch (link_usettings->deprecated.transceiver) {
- 	case XCVR_INTERNAL:
- 		fprintf(stdout, "internal\n");
- 		break;
-@@ -659,17 +760,18 @@ static int dump_ecmd(struct ethtool_cmd *ep)
- 	};
- 
- 	fprintf(stdout, "	Auto-negotiation: %s\n",
--		(ep->autoneg == AUTONEG_DISABLE) ?
-+		(link_usettings->base.autoneg == AUTONEG_DISABLE) ?
- 		"off" : "on");
- 
--	if (ep->port == PORT_TP) {
-+	if (link_usettings->base.port == PORT_TP) {
- 		fprintf(stdout, "	MDI-X: ");
--		if (ep->eth_tp_mdix_ctrl == ETH_TP_MDI) {
-+		if (link_usettings->base.eth_tp_mdix_ctrl == ETH_TP_MDI) {
- 			fprintf(stdout, "off (forced)\n");
--		} else if (ep->eth_tp_mdix_ctrl == ETH_TP_MDI_X) {
-+		} else if (link_usettings->base.eth_tp_mdix_ctrl
-+			   == ETH_TP_MDI_X) {
- 			fprintf(stdout, "on (forced)\n");
- 		} else {
--			switch (ep->eth_tp_mdix) {
-+			switch (link_usettings->base.eth_tp_mdix) {
- 			case ETH_TP_MDI:
- 				fprintf(stdout, "off");
- 				break;
-@@ -680,7 +782,8 @@ static int dump_ecmd(struct ethtool_cmd *ep)
- 				fprintf(stdout, "Unknown");
- 				break;
- 			}
--			if (ep->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO)
-+			if (link_usettings->base.eth_tp_mdix_ctrl
-+			    == ETH_TP_MDI_AUTO)
- 				fprintf(stdout, " (auto)");
- 			fprintf(stdout, "\n");
- 		}
-@@ -1368,6 +1471,7 @@ static int dump_rxfhash(int fhash, u64 val)
- 
- static void dump_eeecmd(struct ethtool_eee *ep)
- {
-+	ETHTOOL_DECLARE_LINK_MODE_MASK(link_mode);
- 
- 	fprintf(stdout, "	EEE status: ");
- 	if (!ep->supported) {
-@@ -1389,9 +1493,16 @@ static void dump_eeecmd(struct ethtool_eee *ep)
- 	else
- 		fprintf(stdout, " disabled\n");
- 
--	dump_link_caps("Supported EEE", "", ep->supported, 1);
--	dump_link_caps("Advertised EEE", "", ep->advertised, 1);
--	dump_link_caps("Link partner advertised EEE", "", ep->lp_advertised, 1);
-+	ethtool_link_mode_zero(link_mode);
-+
-+	link_mode[0] = ep->supported;
-+	dump_link_caps("Supported EEE", "", link_mode, 1);
-+
-+	link_mode[0] = ep->advertised;
-+	dump_link_caps("Advertised EEE", "", link_mode, 1);
-+
-+	link_mode[0] = ep->lp_advertised;
-+	dump_link_caps("Link partner advertised EEE", "", link_mode, 1);
- }
- 
- #define N_SOTS 7
-@@ -2259,10 +2370,220 @@ finish:
- 	return retval;
- }
- 
--static int do_gset(struct cmd_context *ctx)
-+static struct ethtool_link_usettings *
-+do_ioctl_glinksettings(struct cmd_context *ctx)
-+{
-+	int err;
-+	struct {
-+		struct ethtool_link_settings req;
-+		__u32 link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];
-+	} ecmd;
-+	struct ethtool_link_usettings *link_usettings;
-+	unsigned int u32_offs;
-+
-+	/* Handshake with kernel to determine number of words for link
-+	 * mode bitmaps. When requested number of bitmap words is not
-+	 * the one expected by kernel, the latter returns the integer
-+	 * opposite of what it is expecting. We request length 0 below
-+	 * (aka. invalid bitmap length) to get this info.
-+	 */
-+	memset(&ecmd, 0, sizeof(ecmd));
-+	ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
-+	err = send_ioctl(ctx, &ecmd);
-+	if (err < 0)
-+		return NULL;
-+
-+	/* see above: we expect a strictly negative value from kernel.
-+	 */
-+	if (ecmd.req.link_mode_masks_nwords >= 0
-+	    || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
-+		return NULL;
-+
-+	/* got the real ecmd.req.link_mode_masks_nwords,
-+	 * now send the real request
-+	 */
-+	ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
-+	ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
-+	err = send_ioctl(ctx, &ecmd);
-+	if (err < 0)
-+		return NULL;
-+
-+	if (ecmd.req.link_mode_masks_nwords <= 0
-+	    || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
-+		return NULL;
-+
-+	/* Convert to usettings struct */
-+	link_usettings = calloc(1, sizeof(*link_usettings));
-+	if (link_usettings == NULL)
-+		return NULL;
-+
-+	/* keep transceiver 0 */
-+	memcpy(&link_usettings->base, &ecmd.req, sizeof(link_usettings->base));
-+
-+	/* copy link mode bitmaps */
-+	u32_offs = 0;
-+	memcpy(link_usettings->link_modes.supported,
-+	       &ecmd.link_mode_data[u32_offs],
-+	       4 * ecmd.req.link_mode_masks_nwords);
-+
-+	u32_offs += ecmd.req.link_mode_masks_nwords;
-+	memcpy(link_usettings->link_modes.advertising,
-+	       &ecmd.link_mode_data[u32_offs],
-+	       4 * ecmd.req.link_mode_masks_nwords);
-+
-+	u32_offs += ecmd.req.link_mode_masks_nwords;
-+	memcpy(link_usettings->link_modes.lp_advertising,
-+	       &ecmd.link_mode_data[u32_offs],
-+	       4 * ecmd.req.link_mode_masks_nwords);
-+
-+	return link_usettings;
-+}
-+
-+static int
-+do_ioctl_slinksettings(struct cmd_context *ctx,
-+		       const struct ethtool_link_usettings *link_usettings)
-+{
-+	struct {
-+		struct ethtool_link_settings req;
-+		__u32 link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];
-+	} ecmd;
-+	unsigned int u32_offs;
-+
-+	/* refuse to send ETHTOOL_SLINKSETTINGS ioctl if
-+	 * link_usettings was retrieved with ETHTOOL_GSET
-+	 */
-+	if (link_usettings->base.cmd != ETHTOOL_GLINKSETTINGS)
-+		return -1;
-+
-+	/* refuse to send ETHTOOL_SLINKSETTINGS ioctl if deprecated fields
-+	 * were set
-+	 */
-+	if (link_usettings->deprecated.transceiver)
-+		return -1;
-+
-+	if (link_usettings->base.link_mode_masks_nwords <= 0)
-+		return -1;
-+
-+	memcpy(&ecmd.req, &link_usettings->base, sizeof(ecmd.req));
-+	ecmd.req.cmd = ETHTOOL_SLINKSETTINGS;
-+
-+	/* copy link mode bitmaps */
-+	u32_offs = 0;
-+	memcpy(&ecmd.link_mode_data[u32_offs],
-+	       link_usettings->link_modes.supported,
-+	       4 * ecmd.req.link_mode_masks_nwords);
-+
-+	u32_offs += ecmd.req.link_mode_masks_nwords;
-+	memcpy(&ecmd.link_mode_data[u32_offs],
-+	       link_usettings->link_modes.advertising,
-+	       4 * ecmd.req.link_mode_masks_nwords);
-+
-+	u32_offs += ecmd.req.link_mode_masks_nwords;
-+	memcpy(&ecmd.link_mode_data[u32_offs],
-+	       link_usettings->link_modes.lp_advertising,
-+	       4 * ecmd.req.link_mode_masks_nwords);
-+
-+	return send_ioctl(ctx, &ecmd);
-+}
-+
-+static struct ethtool_link_usettings *
-+do_ioctl_gset(struct cmd_context *ctx)
- {
- 	int err;
- 	struct ethtool_cmd ecmd;
-+	struct ethtool_link_usettings *link_usettings;
-+
-+	memset(&ecmd, 0, sizeof(ecmd));
-+	ecmd.cmd = ETHTOOL_GSET;
-+	err = send_ioctl(ctx, &ecmd);
-+	if (err < 0)
-+		return NULL;
-+
-+	link_usettings = calloc(1, sizeof(*link_usettings));
-+	if (link_usettings == NULL)
-+		return NULL;
-+
-+	/* remember that ETHTOOL_GSET was used */
-+	link_usettings->base.cmd = ETHTOOL_GSET;
-+
-+	link_usettings->base.link_mode_masks_nwords = 1;
-+	link_usettings->link_modes.supported[0] = ecmd.supported;
-+	link_usettings->link_modes.advertising[0] = ecmd.advertising;
-+	link_usettings->link_modes.lp_advertising[0] = ecmd.lp_advertising;
-+	link_usettings->base.speed = ethtool_cmd_speed(&ecmd);
-+	link_usettings->base.duplex = ecmd.duplex;
-+	link_usettings->base.port = ecmd.port;
-+	link_usettings->base.phy_address = ecmd.phy_address;
-+	link_usettings->deprecated.transceiver = ecmd.transceiver;
-+	link_usettings->base.autoneg = ecmd.autoneg;
-+	link_usettings->base.mdio_support = ecmd.mdio_support;
-+	/* ignored (fully deprecated): maxrxpkt, maxtxpkt */
-+	link_usettings->base.eth_tp_mdix = ecmd.eth_tp_mdix;
-+	link_usettings->base.eth_tp_mdix_ctrl = ecmd.eth_tp_mdix_ctrl;
-+
-+	return link_usettings;
-+}
-+
-+static bool ethtool_link_mode_is_backward_compatible(const u32 *mask)
-+{
-+	unsigned int i;
-+
-+	for (i = 1; i < ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32; ++i)
-+		if (mask[i])
-+			return false;
-+
-+	return true;
-+}
-+
-+static int
-+do_ioctl_sset(struct cmd_context *ctx,
-+	      const struct ethtool_link_usettings *link_usettings)
-+{
-+	struct ethtool_cmd ecmd;
-+
-+	/* refuse to send ETHTOOL_SSET ioctl if link_usettings was
-+	 * retrieved with ETHTOOL_GLINKSETTINGS
-+	 */
-+	if (link_usettings->base.cmd != ETHTOOL_GSET)
-+		return -1;
-+
-+	if (link_usettings->base.link_mode_masks_nwords <= 0)
-+		return -1;
-+
-+	/* refuse to sset if any bit > 31 is set */
-+	if (!ethtool_link_mode_is_backward_compatible(
-+		    link_usettings->link_modes.supported))
-+		return -1;
-+	if (!ethtool_link_mode_is_backward_compatible(
-+		    link_usettings->link_modes.advertising))
-+		return -1;
-+	if (!ethtool_link_mode_is_backward_compatible(
-+		    link_usettings->link_modes.lp_advertising))
-+		return -1;
-+
-+	memset(&ecmd, 0, sizeof(ecmd));
-+	ecmd.cmd = ETHTOOL_SSET;
-+
-+	ecmd.supported = link_usettings->link_modes.supported[0];
-+	ecmd.advertising = link_usettings->link_modes.advertising[0];
-+	ecmd.lp_advertising = link_usettings->link_modes.lp_advertising[0];
-+	ethtool_cmd_speed_set(&ecmd, link_usettings->base.speed);
-+	ecmd.duplex = link_usettings->base.duplex;
-+	ecmd.port = link_usettings->base.port;
-+	ecmd.phy_address = link_usettings->base.phy_address;
-+	ecmd.transceiver = link_usettings->deprecated.transceiver;
-+	ecmd.autoneg = link_usettings->base.autoneg;
-+	ecmd.mdio_support = link_usettings->base.mdio_support;
-+	/* ignored (fully deprecated): maxrxpkt, maxtxpkt */
-+	ecmd.eth_tp_mdix = link_usettings->base.eth_tp_mdix;
-+	ecmd.eth_tp_mdix_ctrl = link_usettings->base.eth_tp_mdix_ctrl;
-+	return send_ioctl(ctx, &ecmd);
-+}
-+
-+static int do_gset(struct cmd_context *ctx)
-+{
-+	int err;
-+	struct ethtool_link_usettings *link_usettings;
- 	struct ethtool_wolinfo wolinfo;
- 	struct ethtool_value edata;
- 	int allfail = 1;
-@@ -2272,10 +2593,12 @@ static int do_gset(struct cmd_context *ctx)
- 
- 	fprintf(stdout, "Settings for %s:\n", ctx->devname);
- 
--	ecmd.cmd = ETHTOOL_GSET;
--	err = send_ioctl(ctx, &ecmd);
--	if (err == 0) {
--		err = dump_ecmd(&ecmd);
-+	link_usettings = do_ioctl_glinksettings(ctx);
-+	if (link_usettings == NULL)
-+		link_usettings = do_ioctl_gset(ctx);
-+	if (link_usettings != NULL) {
-+		err = dump_link_usettings(link_usettings);
-+		free(link_usettings);
- 		if (err)
- 			return err;
- 		allfail = 0;
-@@ -2334,8 +2657,10 @@ static int do_sset(struct cmd_context *ctx)
- 	int autoneg_wanted = -1;
- 	int phyad_wanted = -1;
- 	int xcvr_wanted = -1;
--	int full_advertising_wanted = -1;
--	int advertising_wanted = -1;
-+	u32 *full_advertising_wanted = NULL;
-+	u32 *advertising_wanted = NULL;
-+	ETHTOOL_DECLARE_LINK_MODE_MASK(mask_full_advertising_wanted);
-+	ETHTOOL_DECLARE_LINK_MODE_MASK(mask_advertising_wanted);
- 	int gset_changed = 0; /* did anything in GSET change? */
- 	u32 wol_wanted = 0;
- 	int wol_change = 0;
-@@ -2349,7 +2674,7 @@ static int do_sset(struct cmd_context *ctx)
- 	int argc = ctx->argc;
- 	char **argp = ctx->argp;
- 	int i;
--	int err;
-+	int err = 0;
- 
- 	for (i = 0; i < ARRAY_SIZE(flags_msglvl); i++)
- 		flag_to_cmdline_info(flags_msglvl[i].name,
-@@ -2423,7 +2748,12 @@ static int do_sset(struct cmd_context *ctx)
- 			i += 1;
- 			if (i >= argc)
- 				exit_bad_args();
--			full_advertising_wanted = get_int(argp[i], 16);
-+			if (parse_hex_u32_bitmap(
-+				    argp[i],
-+				    ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBITS,
-+				    mask_full_advertising_wanted))
-+				exit_bad_args();
-+			full_advertising_wanted = mask_full_advertising_wanted;
- 		} else if (!strcmp(argp[i], "phyad")) {
- 			gset_changed = 1;
- 			i += 1;
-@@ -2480,75 +2810,89 @@ static int do_sset(struct cmd_context *ctx)
- 		}
- 	}
- 
--	if (full_advertising_wanted < 0) {
-+	if (full_advertising_wanted == NULL) {
- 		/* User didn't supply a full advertisement bitfield:
- 		 * construct one from the specified speed and duplex.
- 		 */
-+		int adv_bit = -1;
-+
- 		if (speed_wanted == SPEED_10 && duplex_wanted == DUPLEX_HALF)
--			advertising_wanted = ADVERTISED_10baseT_Half;
-+			adv_bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT;
- 		else if (speed_wanted == SPEED_10 &&
- 			 duplex_wanted == DUPLEX_FULL)
--			advertising_wanted = ADVERTISED_10baseT_Full;
-+			adv_bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT;
- 		else if (speed_wanted == SPEED_100 &&
- 			 duplex_wanted == DUPLEX_HALF)
--			advertising_wanted = ADVERTISED_100baseT_Half;
-+			adv_bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT;
- 		else if (speed_wanted == SPEED_100 &&
- 			 duplex_wanted == DUPLEX_FULL)
--			advertising_wanted = ADVERTISED_100baseT_Full;
-+			adv_bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT;
- 		else if (speed_wanted == SPEED_1000 &&
- 			 duplex_wanted == DUPLEX_HALF)
--			advertising_wanted = ADVERTISED_1000baseT_Half;
-+			adv_bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT;
- 		else if (speed_wanted == SPEED_1000 &&
- 			 duplex_wanted == DUPLEX_FULL)
--			advertising_wanted = ADVERTISED_1000baseT_Full;
-+			adv_bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT;
- 		else if (speed_wanted == SPEED_2500 &&
- 			 duplex_wanted == DUPLEX_FULL)
--			advertising_wanted = ADVERTISED_2500baseX_Full;
-+			adv_bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT;
- 		else if (speed_wanted == SPEED_10000 &&
- 			 duplex_wanted == DUPLEX_FULL)
--			advertising_wanted = ADVERTISED_10000baseT_Full;
--		else
--			/* auto negotiate without forcing,
--			 * all supported speed will be assigned below
--			 */
--			advertising_wanted = 0;
-+			adv_bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT;
-+
-+		if (adv_bit >= 0) {
-+			advertising_wanted = mask_advertising_wanted;
-+			ethtool_link_mode_zero(advertising_wanted);
-+			ethtool_link_mode_set_bit(
-+				adv_bit, advertising_wanted);
-+		}
-+		/* otherwise: auto negotiate without forcing,
-+		 * all supported speed will be assigned below
-+		 */
- 	}
- 
- 	if (gset_changed) {
--		struct ethtool_cmd ecmd;
-+		struct ethtool_link_usettings *link_usettings;
- 
--		ecmd.cmd = ETHTOOL_GSET;
--		err = send_ioctl(ctx, &ecmd);
--		if (err < 0) {
-+		link_usettings = do_ioctl_glinksettings(ctx);
-+		if (link_usettings == NULL)
-+			link_usettings = do_ioctl_gset(ctx);
-+		if (link_usettings == NULL) {
- 			perror("Cannot get current device settings");
-+			err = -1;
- 		} else {
- 			/* Change everything the user specified. */
- 			if (speed_wanted != -1)
--				ethtool_cmd_speed_set(&ecmd, speed_wanted);
-+				link_usettings->base.speed = speed_wanted;
- 			if (duplex_wanted != -1)
--				ecmd.duplex = duplex_wanted;
-+				link_usettings->base.duplex = duplex_wanted;
- 			if (port_wanted != -1)
--				ecmd.port = port_wanted;
-+				link_usettings->base.port = port_wanted;
- 			if (mdix_wanted != -1) {
- 				/* check driver supports MDI-X */
--				if (ecmd.eth_tp_mdix_ctrl != ETH_TP_MDI_INVALID)
--					ecmd.eth_tp_mdix_ctrl = mdix_wanted;
-+				if (link_usettings->base.eth_tp_mdix_ctrl
-+				    != ETH_TP_MDI_INVALID)
-+					link_usettings->base.eth_tp_mdix_ctrl
-+						= mdix_wanted;
- 				else
--					fprintf(stderr, "setting MDI not supported\n");
-+					fprintf(stderr,
-+						"setting MDI not supported\n");
- 			}
- 			if (autoneg_wanted != -1)
--				ecmd.autoneg = autoneg_wanted;
-+				link_usettings->base.autoneg = autoneg_wanted;
- 			if (phyad_wanted != -1)
--				ecmd.phy_address = phyad_wanted;
-+				link_usettings->base.phy_address = phyad_wanted;
- 			if (xcvr_wanted != -1)
--				ecmd.transceiver = xcvr_wanted;
-+				link_usettings->deprecated.transceiver
-+					= xcvr_wanted;
- 			/* XXX If the user specified speed or duplex
- 			 * then we should mask the advertised modes
- 			 * accordingly.  For now, warn that we aren't
- 			 * doing that.
- 			 */
- 			if ((speed_wanted != -1 || duplex_wanted != -1) &&
--			    ecmd.autoneg && advertising_wanted == 0) {
-+			    link_usettings->base.autoneg &&
-+			    advertising_wanted == NULL) {
- 				fprintf(stderr, "Cannot advertise");
- 				if (speed_wanted >= 0)
- 					fprintf(stderr, " speed %d",
-@@ -2560,37 +2904,55 @@ static int do_sset(struct cmd_context *ctx)
- 				fprintf(stderr,	"\n");
- 			}
- 			if (autoneg_wanted == AUTONEG_ENABLE &&
--			    advertising_wanted == 0) {
-+			    advertising_wanted == NULL) {
-+				unsigned int i;
-+
- 				/* Auto negotiation enabled, but with
- 				 * unspecified speed and duplex: enable all
- 				 * supported speeds and duplexes.
- 				 */
--				ecmd.advertising =
--					(ecmd.advertising &
--					 ~ALL_ADVERTISED_MODES) |
--					(ALL_ADVERTISED_MODES & ecmd.supported);
-+				ethtool_link_mode_for_each_u32(i) {
-+					u32 sup = link_usettings->link_modes.supported[i];
-+					u32 *adv = link_usettings->link_modes.advertising + i;
-+
-+					*adv = ((*adv & ~all_advertised_modes[i])
-+						| (sup & all_advertised_modes[i]));
-+				}
- 
- 				/* If driver supports unknown flags, we cannot
- 				 * be sure that we enable all link modes.
- 				 */
--				if ((ecmd.supported & ALL_ADVERTISED_FLAGS) !=
--				    ecmd.supported) {
--					fprintf(stderr, "Driver supports one "
--					        "or more unknown flags\n");
-+				ethtool_link_mode_for_each_u32(i) {
-+					u32 sup = link_usettings->link_modes.supported[i];
-+
-+					if ((sup & all_advertised_flags[i]) != sup) {
-+						fprintf(stderr, "Driver supports one or more unknown flags\n");
-+						break;
-+					}
- 				}
--			} else if (advertising_wanted > 0) {
-+			} else if (advertising_wanted != NULL) {
-+				unsigned int i;
-+
- 				/* Enable all requested modes */
--				ecmd.advertising =
--					(ecmd.advertising &
--					 ~ALL_ADVERTISED_MODES) |
--					advertising_wanted;
--			} else if (full_advertising_wanted > 0) {
--				ecmd.advertising = full_advertising_wanted;
-+				ethtool_link_mode_for_each_u32(i) {
-+					u32 *adv = link_usettings->link_modes.advertising + i;
-+
-+					*adv = ((*adv & ~all_advertised_modes[i])
-+						| advertising_wanted[i]);
-+				}
-+			} else if (full_advertising_wanted != NULL) {
-+				ethtool_link_mode_copy(
-+					link_usettings->link_modes.advertising,
-+					full_advertising_wanted);
- 			}
- 
- 			/* Try to perform the update. */
--			ecmd.cmd = ETHTOOL_SSET;
--			err = send_ioctl(ctx, &ecmd);
-+			if (link_usettings->base.cmd == ETHTOOL_GLINKSETTINGS)
-+				err = do_ioctl_slinksettings(ctx,
-+							     link_usettings);
-+			else
-+				err = do_ioctl_sset(ctx, link_usettings);
-+			free(link_usettings);
- 			if (err < 0)
- 				perror("Cannot set new settings");
- 		}
-@@ -4260,6 +4622,8 @@ int main(int argc, char **argp)
- 	struct cmd_context ctx;
- 	int k;
- 
-+	init_global_link_mode_masks();
-+
- 	/* Skip command name */
- 	argp++;
- 	argc--;
-diff --git a/internal.h b/internal.h
-index e98f532..ef27ab2 100644
---- a/internal.h
-+++ b/internal.h
-@@ -12,6 +12,7 @@
- #ifdef HAVE_CONFIG_H
- #include "ethtool-config.h"
- #endif
-+#include <stdbool.h>
- #include <stdio.h>
- #include <stdint.h>
- #include <stdlib.h>
-@@ -122,6 +123,71 @@ static inline int test_bit(unsigned int nr, const unsigned long *addr)
- 				 ETH_FLAG_TXVLAN | ETH_FLAG_NTUPLE |	\
- 				 ETH_FLAG_RXHASH)
- 
-+/* internal API for link mode bitmap interaction with kernel. */
-+
-+#define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32		\
-+	(SCHAR_MAX)
-+#define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBITS		\
-+	(32 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32)
-+#define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES	\
-+	(4 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32)
-+#define ETHTOOL_DECLARE_LINK_MODE_MASK(name)		\
-+	u32 name[ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]
-+
-+struct ethtool_link_usettings {
-+	struct {
-+		__u8 transceiver;
-+	} deprecated;
-+	struct ethtool_link_settings base;
-+	struct {
-+		ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
-+		ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
-+		ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising);
-+	} link_modes;
-+};
-+
-+#define ethtool_link_mode_for_each_u32(index)			\
-+	for ((index) = 0;					\
-+	     (index) < ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32;	\
-+	     ++(index))
-+
-+static inline void ethtool_link_mode_zero(u32 *dst)
-+{
-+	memset(dst, 0, ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES);
-+}
-+
-+static inline bool ethtool_link_mode_is_empty(const u32 *mask)
-+{
-+	unsigned int i;
-+
-+	ethtool_link_mode_for_each_u32(i) {
-+		if (mask[i] != 0)
-+			return false;
-+	}
-+
-+	return true;
-+}
-+
-+static inline void ethtool_link_mode_copy(u32 *dst, const u32 *src)
-+{
-+	memcpy(dst, src, ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES);
-+}
-+
-+static inline int ethtool_link_mode_test_bit(unsigned int nr, const u32 *mask)
-+{
-+	if (nr >= ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBITS)
-+		return !!0;
-+	return !!(mask[nr / 32] & (1 << (nr % 32)));
-+}
-+
-+static inline int ethtool_link_mode_set_bit(unsigned int nr, u32 *mask)
-+{
-+	if (nr >= ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBITS)
-+		return -1;
-+	mask[nr / 32] |= (1 << (nr % 32));
-+	return 0;
-+}
-+
- /* Context for sub-commands */
- struct cmd_context {
- 	const char *devname;	/* net device name */
-diff --git a/test-cmdline.c b/test-cmdline.c
-index 2fd7cbb..a94edea 100644
---- a/test-cmdline.c
-+++ b/test-cmdline.c
-@@ -37,7 +37,20 @@ static struct test_case {
- 	{ 1, "--change devname autoneg foo" },
- 	{ 1, "-s devname autoneg" },
- 	{ 0, "--change devname advertise 0x1" },
-+	{ 0, "--change devname advertise 0xf" },
-+	{ 0, "--change devname advertise 0Xf" },
-+	{ 0, "--change devname advertise 1" },
-+	{ 0, "--change devname advertise f" },
-+	{ 0, "--change devname advertise 01" },
-+	{ 0, "--change devname advertise 0f" },
-+	{ 0, "--change devname advertise 0xfffffffffffffffffffffffffffffffff" },
-+	{ 0, "--change devname advertise fffffffffffffffffffffffffffffffff" },
-+	{ 0, "--change devname advertise 0x0000fffffffffffffffffffffffffffff" },
-+	{ 0, "--change devname advertise 0000fffffffffffffffffffffffffffff" },
-+	{ 1, "-s devname advertise" },
-+	{ 1, "-s devname advertise 0x" },
- 	{ 1, "-s devname advertise foo" },
-+	{ 1, "-s devname advertise 0xfoo" },
- 	{ 1, "--change devname advertise" },
- 	{ 0, "-s devname phyad 1" },
- 	{ 1, "--change devname phyad foo" },
--- 
-1.8.3.1
-
diff --git a/SOURCES/0003-ethtool-Fix-the-advertise-parameter-logic.patch b/SOURCES/0003-ethtool-Fix-the-advertise-parameter-logic.patch
new file mode 100644
index 0000000..8f47dc2
--- /dev/null
+++ b/SOURCES/0003-ethtool-Fix-the-advertise-parameter-logic.patch
@@ -0,0 +1,44 @@
+From 47b95959941b3d7d2d35a128da5685799329aaf6 Mon Sep 17 00:00:00 2001
+From: Michael Chan <mchan@broadcom.com>
+Date: Tue, 22 Nov 2016 18:55:47 -0500
+Subject: [PATCH 3/3] ethtool: Fix the "advertise" parameter logic.
+
+The current code ignores the value of the advertise parameter.  For example,
+
+ethtool -s ethx advertise 0x1000
+
+The full_advertising_wanted parameter of 0x1000 is not passed to the kernel.
+The reason is that advertising_wanted is NULL in this case, and ethtool
+will think that the user has given no advertisement input and so it will
+proceed to pass all supported advertisement speeds to the kernel.
+
+The older legacy ethtool with similar logic worked because
+advertising_wanted was an integer and could take on -1 and 0.  It would pass
+the full_advertising_wanted value if advertising_wanted == -1.
+
+This fix is to pass all supported advertisement speeds only when both
+advertising_wanted == NULL && full_advertising_wanted == NULL.
+
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+---
+ ethtool.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/ethtool.c b/ethtool.c
+index 0d3244e..ce48639 100644
+--- a/ethtool.c
++++ b/ethtool.c
+@@ -2972,7 +2972,8 @@ static int do_sset(struct cmd_context *ctx)
+ 				fprintf(stderr,	"\n");
+ 			}
+ 			if (autoneg_wanted == AUTONEG_ENABLE &&
+-			    advertising_wanted == NULL) {
++			    advertising_wanted == NULL &&
++			    full_advertising_wanted == NULL) {
+ 				unsigned int i;
+ 
+ 				/* Auto negotiation enabled, but with
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0003-ethtool-copy.h-sync-with-net.patch b/SOURCES/0003-ethtool-copy.h-sync-with-net.patch
deleted file mode 100644
index b4fb20b..0000000
--- a/SOURCES/0003-ethtool-copy.h-sync-with-net.patch
+++ /dev/null
@@ -1,74 +0,0 @@
-From c3a3768ddec648ddc15402b8054ee1b4d3b2f336 Mon Sep 17 00:00:00 2001
-From: Vidya Sagar Ravipati <vidya@cumulusnetworks.com>
-Date: Tue, 23 Aug 2016 06:30:30 -0700
-Subject: [PATCH 3/7] ethtool-copy.h:sync with net
-
-This covers kernel changes upto:
-
-commit 89da45b8b5b2187734a11038b8593714f964ffd1
-Author: Gal Pressman <galp@mellanox.com>
-Date:   Thu Jun 23 17:02:43 2016 +0300
-
-    ethtool: Add 50G baseSR2 link mode
-
-    Add ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT bit.
-
-    Signed-off-by: Gal Pressman <galp@mellanox.com>
-    Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
-    Cc: Ben Hutchings <bwh@kernel.org>
-    Cc: David Decotigny <decot@googlers.com>
-    Acked-By: David Decotigny <decot@googlers.com>
-    Signed-off-by: David S. Miller <davem@davemloft.net>
-
-Signed-off-by: John W. Linville <linville@tuxdriver.com>
-(cherry picked from commit c431e762fadca8648d78d0e7e1842e1a0c9ac309)
----
- ethtool-copy.h | 18 ++++++++++++++----
- 1 file changed, 14 insertions(+), 4 deletions(-)
-
-diff --git a/ethtool-copy.h b/ethtool-copy.h
-index 7c581ea..246f7b0 100644
---- a/ethtool-copy.h
-+++ b/ethtool-copy.h
-@@ -1351,6 +1351,16 @@ enum ethtool_link_mode_bit_indices {
- 	ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT	= 28,
- 	ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT	= 29,
- 	ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT	= 30,
-+	ETHTOOL_LINK_MODE_25000baseCR_Full_BIT	= 31,
-+	ETHTOOL_LINK_MODE_25000baseKR_Full_BIT	= 32,
-+	ETHTOOL_LINK_MODE_25000baseSR_Full_BIT	= 33,
-+	ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT	= 34,
-+	ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT	= 35,
-+	ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT	= 36,
-+	ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT	= 37,
-+	ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT	= 38,
-+	ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT	= 39,
-+	ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT         = 40,
- 
- 	/* Last allowed bit for __ETHTOOL_LINK_MODE_LEGACY_MASK is bit
- 	 * 31. Please do NOT define any SUPPORTED_* or ADVERTISED_*
-@@ -1359,7 +1369,7 @@ enum ethtool_link_mode_bit_indices {
- 	 */
- 
- 	__ETHTOOL_LINK_MODE_LAST
--	  = ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
-+	  = ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
- };
- 
- #define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name)	\
-@@ -1646,9 +1656,9 @@ enum ethtool_reset_flags {
-  *	%ETHTOOL_GLINKSETTINGS: on entry, number of words passed by user
-  *	(>= 0); on return, if handshake in progress, negative if
-  *	request size unsupported by kernel: absolute value indicates
-- *	kernel recommended size and cmd field is 0, as well as all the
-- *	other fields; otherwise (handshake completed), strictly
-- *	positive to indicate size used by kernel and cmd field is
-+ *	kernel expected size and all the other fields but cmd
-+ *	are 0; otherwise (handshake completed), strictly positive
-+ *	to indicate size used by kernel and cmd field stays
-  *	%ETHTOOL_GLINKSETTINGS, all other fields populated by driver. For
-  *	%ETHTOOL_SLINKSETTINGS: must be valid on entry, ie. a positive
-  *	value returned previously by %ETHTOOL_GLINKSETTINGS, otherwise
--- 
-1.8.3.1
-
diff --git a/SOURCES/0004-ethtool-Reorganizing-SFF-8024-fields-for-SFP-QSFP.patch b/SOURCES/0004-ethtool-Reorganizing-SFF-8024-fields-for-SFP-QSFP.patch
deleted file mode 100644
index 3e6de4d..0000000
--- a/SOURCES/0004-ethtool-Reorganizing-SFF-8024-fields-for-SFP-QSFP.patch
+++ /dev/null
@@ -1,872 +0,0 @@
-From 0173e95eb07cef9f189299a040e11f31de15f638 Mon Sep 17 00:00:00 2001
-From: Vidya Sagar Ravipati <vidya@cumulusnetworks.com>
-Date: Tue, 23 Aug 2016 06:30:31 -0700
-Subject: [PATCH 4/7] ethtool:Reorganizing SFF-8024 fields for SFP/QSFP
-
-This patch provides following support
-a) Reorganized fields based out of SFF-8024 fields i.e. Identifier/
-   Encoding/Connector types which are common across SFP/SFP+ (SFF-8472)
-   and QSFP+/QSFP28 (SFF-8436/SFF-8636) modules into sff-common files.
-b) Moving the common functions for SFP+ and QSFP+ DOM into sff-common
-   files
-
-Standards for SFF-8024
-a) SFF-8024 Rev 4.0 dated May 31, 2016
-
-Signed-off-by: Vidya Sagar Ravipati <vidya@cumulusnetworks.com>
-Acked-by: Bert Kenward <bkenward@solarflare.com>
-Signed-off-by: John W. Linville <linville@tuxdriver.com>
-(cherry picked from commit 7a4c42258e3038ff943c1e27c74b4bca2d3190a0)
----
- Makefile.am  |   3 +-
- sff-common.c | 304 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- sff-common.h | 189 +++++++++++++++++++++++++++++++++++++
- sfpdiag.c    | 105 +++------------------
- sfpid.c      | 103 +-------------------
- 5 files changed, 511 insertions(+), 193 deletions(-)
- create mode 100644 sff-common.c
- create mode 100644 sff-common.h
-
-diff --git a/Makefile.am b/Makefile.am
-index 6814bc9..3c9f387 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -13,7 +13,8 @@ ethtool_SOURCES += \
- 		  fec_8xx.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	\
--		  sfpid.c sfpdiag.c ixgbevf.c tse.c vmxnet3.c
-+		  sff-common.c sff-common.h sfpid.c sfpdiag.c	\
-+		  ixgbevf.c tse.c vmxnet3.c
- endif
- 
- TESTS = test-cmdline test-features
-diff --git a/sff-common.c b/sff-common.c
-new file mode 100644
-index 0000000..7700cbe
---- /dev/null
-+++ b/sff-common.c
-@@ -0,0 +1,304 @@
-+/*
-+ * sff-common.c: Implements SFF-8024 Rev 4.0 i.e. Specifcation
-+ * of pluggable I/O configuration
-+ *
-+ * Common utilities across SFF-8436/8636 and SFF-8472/8079
-+ * are defined in this file
-+ *
-+ * Copyright 2010 Solarflare Communications Inc.
-+ * Aurelien Guillaume <aurelien@iwi.me> (C) 2012
-+ * Copyright (C) 2014 Cumulus networks Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Freeoftware Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ *  Vidya Sagar Ravipati <vidya@cumulusnetworks.com>
-+ *   This implementation is loosely based on current SFP parser
-+ *   and SFF-8024 Rev 4.0 spec (ftp://ftp.seagate.com/pub/sff/SFF-8024.PDF)
-+ *   by SFF Committee.
-+ */
-+
-+#include <stdio.h>
-+#include <math.h>
-+#include "sff-common.h"
-+
-+double convert_mw_to_dbm(double mw)
-+{
-+	return (10. * log10(mw / 1000.)) + 30.;
-+}
-+
-+void sff_show_value_with_unit(const __u8 *id, unsigned int reg,
-+			      const char *name, unsigned int mult,
-+			      const char *unit)
-+{
-+	unsigned int val = id[reg];
-+
-+	printf("\t%-41s : %u%s\n", name, val * mult, unit);
-+}
-+
-+void sff_show_ascii(const __u8 *id, unsigned int first_reg,
-+		    unsigned int last_reg, const char *name)
-+{
-+	unsigned int reg, val;
-+
-+	printf("\t%-41s : ", name);
-+	while (first_reg <= last_reg && id[last_reg] == ' ')
-+		last_reg--;
-+	for (reg = first_reg; reg <= last_reg; reg++) {
-+		val = id[reg];
-+		putchar(((val >= 32) && (val <= 126)) ? val : '_');
-+	}
-+	printf("\n");
-+}
-+
-+void sff8024_show_oui(const __u8 *id, int id_offset)
-+{
-+	printf("\t%-41s : %02x:%02x:%02x\n", "Vendor OUI",
-+		      id[id_offset], id[(id_offset) + 1],
-+		      id[(id_offset) + 2]);
-+}
-+
-+void sff8024_show_identifier(const __u8 *id, int id_offset)
-+{
-+	printf("\t%-41s : 0x%02x", "Identifier", id[id_offset]);
-+	switch (id[id_offset]) {
-+	case SFF8024_ID_UNKNOWN:
-+		printf(" (no module present, unknown, or unspecified)\n");
-+		break;
-+	case SFF8024_ID_GBIC:
-+		printf(" (GBIC)\n");
-+		break;
-+	case SFF8024_ID_SOLDERED_MODULE:
-+		printf(" (module soldered to motherboard)\n");
-+		break;
-+	case SFF8024_ID_SFP:
-+		printf(" (SFP)\n");
-+		break;
-+	case SFF8024_ID_300_PIN_XBI:
-+		printf(" (300 pin XBI)\n");
-+		break;
-+	case SFF8024_ID_XENPAK:
-+		printf(" (XENPAK)\n");
-+		break;
-+	case SFF8024_ID_XFP:
-+		printf(" (XFP)\n");
-+		break;
-+	case SFF8024_ID_XFF:
-+		printf(" (XFF)\n");
-+		break;
-+	case SFF8024_ID_XFP_E:
-+		printf(" (XFP-E)\n");
-+		break;
-+	case SFF8024_ID_XPAK:
-+		printf(" (XPAK)\n");
-+		break;
-+	case SFF8024_ID_X2:
-+		printf(" (X2)\n");
-+		break;
-+	case SFF8024_ID_DWDM_SFP:
-+		printf(" (DWDM-SFP)\n");
-+		break;
-+	case SFF8024_ID_QSFP:
-+		printf(" (QSFP)\n");
-+		break;
-+	case SFF8024_ID_QSFP_PLUS:
-+		printf(" (QSFP+)\n");
-+		break;
-+	case SFF8024_ID_CXP:
-+		printf(" (CXP)\n");
-+		break;
-+	case SFF8024_ID_HD4X:
-+		printf(" (Shielded Mini Multilane HD 4X)\n");
-+		break;
-+	case SFF8024_ID_HD8X:
-+		printf(" (Shielded Mini Multilane HD 8X)\n");
-+		break;
-+	case SFF8024_ID_QSFP28:
-+		printf(" (QSFP28)\n");
-+		break;
-+	case SFF8024_ID_CXP2:
-+		printf(" (CXP2/CXP28)\n");
-+		break;
-+	case SFF8024_ID_CDFP:
-+		printf(" (CDFP Style 1/Style 2)\n");
-+		break;
-+	case SFF8024_ID_HD4X_FANOUT:
-+		printf(" (Shielded Mini Multilane HD 4X Fanout Cable)\n");
-+		break;
-+	case SFF8024_ID_HD8X_FANOUT:
-+		printf(" (Shielded Mini Multilane HD 8X Fanout Cable)\n");
-+		break;
-+	case SFF8024_ID_CDFP_S3:
-+		printf(" (CDFP Style 3)\n");
-+		break;
-+	case SFF8024_ID_MICRO_QSFP:
-+		printf(" (microQSFP)\n");
-+		break;
-+	default:
-+		printf(" (reserved or unknown)\n");
-+		break;
-+	}
-+}
-+
-+void sff8024_show_connector(const __u8 *id, int ctor_offset)
-+{
-+	printf("\t%-41s : 0x%02x", "Connector", id[ctor_offset]);
-+	switch (id[ctor_offset]) {
-+	case  SFF8024_CTOR_UNKNOWN:
-+		printf(" (unknown or unspecified)\n");
-+		break;
-+	case SFF8024_CTOR_SC:
-+		printf(" (SC)\n");
-+		break;
-+	case SFF8024_CTOR_FC_STYLE_1:
-+		printf(" (Fibre Channel Style 1 copper)\n");
-+		break;
-+	case SFF8024_CTOR_FC_STYLE_2:
-+		printf(" (Fibre Channel Style 2 copper)\n");
-+		break;
-+	case SFF8024_CTOR_BNC_TNC:
-+		printf(" (BNC/TNC)\n");
-+		break;
-+	case SFF8024_CTOR_FC_COAX:
-+		printf(" (Fibre Channel coaxial headers)\n");
-+		break;
-+	case SFF8024_CTOR_FIBER_JACK:
-+		printf(" (FibreJack)\n");
-+		break;
-+	case SFF8024_CTOR_LC:
-+		printf(" (LC)\n");
-+		break;
-+	case SFF8024_CTOR_MT_RJ:
-+		printf(" (MT-RJ)\n");
-+		break;
-+	case SFF8024_CTOR_MU:
-+		printf(" (MU)\n");
-+		break;
-+	case SFF8024_CTOR_SG:
-+		printf(" (SG)\n");
-+		break;
-+	case SFF8024_CTOR_OPT_PT:
-+		printf(" (Optical pigtail)\n");
-+		break;
-+	case SFF8024_CTOR_MPO:
-+		printf(" (MPO Parallel Optic)\n");
-+		break;
-+	case SFF8024_CTOR_MPO_2:
-+		printf(" (MPO Parallel Optic - 2x16)\n");
-+		break;
-+	case SFF8024_CTOR_HSDC_II:
-+		printf(" (HSSDC II)\n");
-+		break;
-+	case SFF8024_CTOR_COPPER_PT:
-+		printf(" (Copper pigtail)\n");
-+		break;
-+	case SFF8024_CTOR_RJ45:
-+		printf(" (RJ45)\n");
-+		break;
-+	case SFF8024_CTOR_NO_SEPARABLE:
-+		printf(" (No separable connector)\n");
-+		break;
-+	case SFF8024_CTOR_MXC_2x16:
-+		printf(" (MXC 2x16)\n");
-+		break;
-+	default:
-+		printf(" (reserved or unknown)\n");
-+		break;
-+	}
-+}
-+
-+void sff8024_show_encoding(const __u8 *id, int encoding_offset, int sff_type)
-+{
-+	printf("\t%-41s : 0x%02x", "Encoding", id[encoding_offset]);
-+	switch (id[encoding_offset]) {
-+	case SFF8024_ENCODING_UNSPEC:
-+		printf(" (unspecified)\n");
-+		break;
-+	case SFF8024_ENCODING_8B10B:
-+		printf(" (8B/10B)\n");
-+		break;
-+	case SFF8024_ENCODING_4B5B:
-+		printf(" (4B/5B)\n");
-+		break;
-+	case SFF8024_ENCODING_NRZ:
-+		printf(" (NRZ)\n");
-+		break;
-+	case SFF8024_ENCODING_4h:
-+		if (sff_type == ETH_MODULE_SFF_8472)
-+			printf(" (Manchester)\n");
-+		else if (sff_type == ETH_MODULE_SFF_8636)
-+			printf(" (SONET Scrambled)\n");
-+		break;
-+	case SFF8024_ENCODING_5h:
-+		if (sff_type == ETH_MODULE_SFF_8472)
-+			printf(" (SONET Scrambled)\n");
-+		else if (sff_type == ETH_MODULE_SFF_8636)
-+			printf(" (64B/66B)\n");
-+		break;
-+	case SFF8024_ENCODING_6h:
-+		if (sff_type == ETH_MODULE_SFF_8472)
-+			printf(" (64B/66B)\n");
-+		else if (sff_type == ETH_MODULE_SFF_8636)
-+			printf(" (Manchester)\n");
-+		break;
-+	case SFF8024_ENCODING_256B:
-+		printf(" ((256B/257B (transcoded FEC-enabled data))\n");
-+		break;
-+	case SFF8024_ENCODING_PAM4:
-+		printf(" (PAM4)\n");
-+		break;
-+	default:
-+		printf(" (reserved or unknown)\n");
-+		break;
-+	}
-+}
-+
-+void sff_show_thresholds(struct sff_diags sd)
-+{
-+	PRINT_BIAS("Laser bias current high alarm threshold",
-+		   sd.bias_cur[HALRM]);
-+	PRINT_BIAS("Laser bias current low alarm threshold",
-+		   sd.bias_cur[LALRM]);
-+	PRINT_BIAS("Laser bias current high warning threshold",
-+		   sd.bias_cur[HWARN]);
-+	PRINT_BIAS("Laser bias current low warning threshold",
-+		   sd.bias_cur[LWARN]);
-+
-+	PRINT_xX_PWR("Laser output power high alarm threshold",
-+		     sd.tx_power[HALRM]);
-+	PRINT_xX_PWR("Laser output power low alarm threshold",
-+		     sd.tx_power[LALRM]);
-+	PRINT_xX_PWR("Laser output power high warning threshold",
-+		     sd.tx_power[HWARN]);
-+	PRINT_xX_PWR("Laser output power low warning threshold",
-+		     sd.tx_power[LWARN]);
-+
-+	PRINT_TEMP("Module temperature high alarm threshold",
-+		   sd.sfp_temp[HALRM]);
-+	PRINT_TEMP("Module temperature low alarm threshold",
-+		   sd.sfp_temp[LALRM]);
-+	PRINT_TEMP("Module temperature high warning threshold",
-+		   sd.sfp_temp[HWARN]);
-+	PRINT_TEMP("Module temperature low warning threshold",
-+		   sd.sfp_temp[LWARN]);
-+
-+	PRINT_VCC("Module voltage high alarm threshold",
-+		  sd.sfp_voltage[HALRM]);
-+	PRINT_VCC("Module voltage low alarm threshold",
-+		  sd.sfp_voltage[LALRM]);
-+	PRINT_VCC("Module voltage high warning threshold",
-+		  sd.sfp_voltage[HWARN]);
-+	PRINT_VCC("Module voltage low warning threshold",
-+		  sd.sfp_voltage[LWARN]);
-+
-+	PRINT_xX_PWR("Laser rx power high alarm threshold",
-+		     sd.rx_power[HALRM]);
-+	PRINT_xX_PWR("Laser rx power low alarm threshold",
-+		     sd.rx_power[LALRM]);
-+	PRINT_xX_PWR("Laser rx power high warning threshold",
-+		     sd.rx_power[HWARN]);
-+	PRINT_xX_PWR("Laser rx power low warning threshold",
-+		     sd.rx_power[LWARN]);
-+}
-diff --git a/sff-common.h b/sff-common.h
-new file mode 100644
-index 0000000..5562b4d
---- /dev/null
-+++ b/sff-common.h
-@@ -0,0 +1,189 @@
-+/*
-+ * sff-common.h: Implements SFF-8024 Rev 4.0 i.e. Specifcation
-+ * of pluggable I/O configuration
-+ *
-+ * Common utilities across SFF-8436/8636 and SFF-8472/8079
-+ * are defined in this file
-+ *
-+ * Copyright 2010 Solarflare Communications Inc.
-+ * Aurelien Guillaume <aurelien@iwi.me> (C) 2012
-+ * Copyright (C) 2014 Cumulus networks Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Freeoftware Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ *  Vidya Sagar Ravipati <vidya@cumulusnetworks.com>
-+ *   This implementation is loosely based on current SFP parser
-+ *   and SFF-8024 specs (ftp://ftp.seagate.com/pub/sff/SFF-8024.PDF)
-+ *   by SFF Committee.
-+ */
-+
-+#ifndef SFF_COMMON_H__
-+#define SFF_COMMON_H__
-+
-+#include <stdio.h>
-+#include "internal.h"
-+
-+#define SFF8024_ID_OFFSET				0x00
-+#define  SFF8024_ID_UNKNOWN				0x00
-+#define  SFF8024_ID_GBIC				0x01
-+#define  SFF8024_ID_SOLDERED_MODULE		0x02
-+#define  SFF8024_ID_SFP					0x03
-+#define  SFF8024_ID_300_PIN_XBI			0x04
-+#define  SFF8024_ID_XENPAK				0x05
-+#define  SFF8024_ID_XFP					0x06
-+#define  SFF8024_ID_XFF					0x07
-+#define  SFF8024_ID_XFP_E				0x08
-+#define  SFF8024_ID_XPAK				0x09
-+#define  SFF8024_ID_X2					0x0A
-+#define  SFF8024_ID_DWDM_SFP			0x0B
-+#define  SFF8024_ID_QSFP				0x0C
-+#define  SFF8024_ID_QSFP_PLUS			0x0D
-+#define  SFF8024_ID_CXP					0x0E
-+#define  SFF8024_ID_HD4X				0x0F
-+#define  SFF8024_ID_HD8X				0x10
-+#define  SFF8024_ID_QSFP28				0x11
-+#define  SFF8024_ID_CXP2				0x12
-+#define  SFF8024_ID_CDFP				0x13
-+#define  SFF8024_ID_HD4X_FANOUT			0x14
-+#define  SFF8024_ID_HD8X_FANOUT			0x15
-+#define  SFF8024_ID_CDFP_S3				0x16
-+#define  SFF8024_ID_MICRO_QSFP			0x17
-+#define  SFF8024_ID_LAST				SFF8024_ID_MICRO_QSFP
-+#define  SFF8024_ID_UNALLOCATED_LAST	0x7F
-+#define  SFF8024_ID_VENDOR_START		0x80
-+#define  SFF8024_ID_VENDOR_LAST			0xFF
-+
-+#define  SFF8024_CTOR_UNKNOWN			0x00
-+#define  SFF8024_CTOR_SC				0x01
-+#define  SFF8024_CTOR_FC_STYLE_1		0x02
-+#define  SFF8024_CTOR_FC_STYLE_2		0x03
-+#define  SFF8024_CTOR_BNC_TNC			0x04
-+#define  SFF8024_CTOR_FC_COAX			0x05
-+#define  SFF8024_CTOR_FIBER_JACK		0x06
-+#define  SFF8024_CTOR_LC				0x07
-+#define  SFF8024_CTOR_MT_RJ				0x08
-+#define  SFF8024_CTOR_MU				0x09
-+#define  SFF8024_CTOR_SG				0x0A
-+#define  SFF8024_CTOR_OPT_PT			0x0B
-+#define  SFF8024_CTOR_MPO				0x0C
-+#define  SFF8024_CTOR_MPO_2				0x0D
-+/* 0E-1Fh --- Reserved */
-+#define  SFF8024_CTOR_HSDC_II			0x20
-+#define  SFF8024_CTOR_COPPER_PT			0x21
-+#define  SFF8024_CTOR_RJ45				0x22
-+#define  SFF8024_CTOR_NO_SEPARABLE		0x23
-+#define  SFF8024_CTOR_MXC_2x16			0x24
-+#define  SFF8024_CTOR_LAST				SFF8024_CTOR_MXC_2x16
-+#define  SFF8024_CTOR_UNALLOCATED_LAST	0x7F
-+#define  SFF8024_CTOR_VENDOR_START		0x80
-+#define  SFF8024_CTOR_VENDOR_LAST		0xFF
-+
-+/* ENCODING Values */
-+#define  SFF8024_ENCODING_UNSPEC		0x00
-+#define  SFF8024_ENCODING_8B10B			0x01
-+#define  SFF8024_ENCODING_4B5B			0x02
-+#define  SFF8024_ENCODING_NRZ			0x03
-+/*
-+ * Value: 04h
-+ * SFF-8472      - Manchester
-+ * SFF-8436/8636 - SONET Scrambled
-+ */
-+#define  SFF8024_ENCODING_4h			0x04
-+/*
-+ * Value: 05h
-+ * SFF-8472      - SONET Scrambled
-+ * SFF-8436/8636 - 64B/66B
-+ */
-+#define  SFF8024_ENCODING_5h			0x05
-+/*
-+ * Value: 06h
-+ * SFF-8472      - 64B/66B
-+ * SFF-8436/8636 - Manchester
-+ */
-+#define  SFF8024_ENCODING_6h			0x06
-+#define  SFF8024_ENCODING_256B			0x07
-+#define  SFF8024_ENCODING_PAM4			0x08
-+
-+/* Most common case: 16-bit unsigned integer in a certain unit */
-+#define OFFSET_TO_U16(offset) \
-+		(id[offset] << 8 | id[(offset) + 1])
-+
-+# define PRINT_xX_PWR(string, var)                             \
-+		printf("\t%-41s : %.4f mW / %.2f dBm\n", (string),         \
-+		      (double)((var) / 10000.),                           \
-+		       convert_mw_to_dbm((double)((var) / 10000.)))
-+
-+#define PRINT_BIAS(string, bias_cur)                             \
-+		printf("\t%-41s : %.3f mA\n", (string),                       \
-+		      (double)(bias_cur / 500.))
-+
-+#define PRINT_TEMP(string, temp)                                   \
-+		printf("\t%-41s : %.2f degrees C / %.2f degrees F\n", \
-+		      (string), (double)(temp / 256.),                \
-+		      (double)(temp / 256. * 1.8 + 32.))
-+
-+#define PRINT_VCC(string, sfp_voltage)          \
-+		printf("\t%-41s : %.4f V\n", (string),       \
-+		      (double)(sfp_voltage / 10000.))
-+
-+# define PRINT_xX_THRESH_PWR(string, var, index)                       \
-+		PRINT_xX_PWR(string, (var)[(index)])
-+
-+/* Channel Monitoring Fields */
-+struct sff_channel_diags {
-+	__u16 bias_cur;      /* Measured bias current in 2uA units */
-+	__u16 rx_power;      /* Measured RX Power */
-+	__u16 tx_power;      /* Measured TX Power */
-+};
-+
-+/* Module Monitoring Fields */
-+struct sff_diags {
-+
-+#define MAX_CHANNEL_NUM 4
-+#define LWARN 0
-+#define HWARN 1
-+#define LALRM 2
-+#define HALRM 3
-+#define MCURR 4
-+
-+	/* Supports DOM */
-+	__u8 supports_dom;
-+	/* Supports alarm/warning thold */
-+	__u8 supports_alarms;
-+	/* RX Power: 0 = OMA, 1 = Average power */
-+	__u8  rx_power_type;
-+	/* TX Power: 0 = Not supported, 1 = Average power */
-+	__u8  tx_power_type;
-+
-+	__u8 calibrated_ext;    /* Is externally calibrated */
-+	/* [5] tables are low/high warn, low/high alarm, current */
-+	/* SFP voltage in 0.1mV units */
-+	__u16 sfp_voltage[5];
-+	/* SFP Temp in 16-bit signed 1/256 Celcius */
-+	__s16 sfp_temp[5];
-+	/* Measured bias current in 2uA units */
-+	__u16 bias_cur[5];
-+	/* Measured TX Power */
-+	__u16 tx_power[5];
-+	/* Measured RX Power */
-+	__u16 rx_power[5];
-+	struct sff_channel_diags scd[MAX_CHANNEL_NUM];
-+};
-+
-+double convert_mw_to_dbm(double mw);
-+void sff_show_value_with_unit(const __u8 *id, unsigned int reg,
-+			      const char *name, unsigned int mult,
-+			      const char *unit);
-+void sff_show_ascii(const __u8 *id, unsigned int first_reg,
-+		    unsigned int last_reg, const char *name);
-+void sff_show_thresholds(struct sff_diags sd);
-+
-+void sff8024_show_oui(const __u8 *id, int id_offset);
-+void sff8024_show_identifier(const __u8 *id, int id_offset);
-+void sff8024_show_connector(const __u8 *id, int ctor_offset);
-+void sff8024_show_encoding(const __u8 *id, int encoding_offset, int sff_type);
-+
-+#endif /* SFF_COMMON_H__ */
-diff --git a/sfpdiag.c b/sfpdiag.c
-index a3dbc9b..32e4cd8 100644
---- a/sfpdiag.c
-+++ b/sfpdiag.c
-@@ -12,6 +12,7 @@
- #include <math.h>
- #include <arpa/inet.h>
- #include "internal.h"
-+#include "sff-common.h"
- 
- /* Offsets in decimal, for direct comparison with the SFF specs */
- 
-@@ -86,28 +87,6 @@
- #define SFF_A2_CAL_V_SLP                  88
- #define SFF_A2_CAL_V_OFF                  90
- 
--
--struct sff8472_diags {
--
--#define MCURR 0
--#define LWARN 1
--#define HWARN 2
--#define LALRM 3
--#define HALRM 4
--
--	/* [5] tables are current, low/high warn, low/high alarm */
--	__u8 supports_dom;      /* Supports DOM */
--	__u8 supports_alarms;   /* Supports alarm/warning thold */
--	__u8 calibrated_ext;    /* Is externally calibrated */
--	__u16 bias_cur[5];      /* Measured bias current in 2uA units */
--	__u16 tx_power[5];      /* Measured TX Power in 0.1uW units */
--	__u16 rx_power[5];      /* Measured RX Power */
--	__u8  rx_power_type;    /* 0 = OMA, 1 = Average power */
--	__s16 sfp_temp[5];      /* SFP Temp in 16-bit signed 1/256 Celsius */
--	__u16 sfp_voltage[5];   /* SFP voltage in 0.1mV units */
--
--};
--
- static struct sff8472_aw_flags {
- 	const char *str;        /* Human-readable string, null at the end */
- 	int offset;             /* A2-relative address offset */
-@@ -141,12 +120,6 @@ static struct sff8472_aw_flags {
- 	{ NULL, 0, 0 },
- };
- 
--static double convert_mw_to_dbm(double mw)
--{
--	return (10. * log10(mw / 1000.)) + 30.;
--}
--
--
- /* Most common case: 16-bit unsigned integer in a certain unit */
- #define A2_OFFSET_TO_U16(offset) \
- 	(id[SFF_A2_BASE + (offset)] << 8 | id[SFF_A2_BASE + (offset) + 1])
-@@ -170,10 +143,8 @@ static double convert_mw_to_dbm(double mw)
-  */
- #define A2_OFFSET_TO_TEMP(offset) ((__s16)A2_OFFSET_TO_U16(offset))
- 
--
--static void sff8472_dom_parse(const __u8 *id, struct sff8472_diags *sd)
-+static void sff8472_dom_parse(const __u8 *id, struct sff_diags *sd)
- {
--
- 	sd->bias_cur[MCURR] = A2_OFFSET_TO_U16(SFF_A2_BIAS);
- 	sd->bias_cur[HALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_HALRM);
- 	sd->bias_cur[LALRM] = A2_OFFSET_TO_U16(SFF_A2_BIAS_LALRM);
-@@ -203,7 +174,6 @@ static void sff8472_dom_parse(const __u8 *id, struct sff8472_diags *sd)
- 	sd->sfp_temp[LALRM] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LALRM);
- 	sd->sfp_temp[HWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_HWARN);
- 	sd->sfp_temp[LWARN] = A2_OFFSET_TO_TEMP(SFF_A2_TEMP_LWARN);
--
- }
- 
- /* Converts to a float from a big-endian 4-byte source buffer. */
-@@ -218,7 +188,7 @@ static float befloattoh(const __u32 *source)
- 	return converter.dst;
- }
- 
--static void sff8472_calibration(const __u8 *id, struct sff8472_diags *sd)
-+static void sff8472_calibration(const __u8 *id, struct sff_diags *sd)
- {
- 	int i;
- 	__u16 rx_reading;
-@@ -252,7 +222,7 @@ static void sff8472_calibration(const __u8 *id, struct sff8472_diags *sd)
- 	}
- }
- 
--static void sff8472_parse_eeprom(const __u8 *id, struct sff8472_diags *sd)
-+static void sff8472_parse_eeprom(const __u8 *id, struct sff_diags *sd)
- {
- 	sd->supports_dom = id[SFF_A0_DOM] & SFF_A0_DOM_IMPL;
- 	sd->supports_alarms = id[SFF_A0_OPTIONS] & SFF_A0_OPTIONS_AW;
-@@ -271,7 +241,7 @@ static void sff8472_parse_eeprom(const __u8 *id, struct sff8472_diags *sd)
- 
- void sff8472_show_all(const __u8 *id)
- {
--	struct sff8472_diags sd;
-+	struct sff_diags sd;
- 	char *rx_power_string = NULL;
- 	int i;
- 
-@@ -279,40 +249,22 @@ void sff8472_show_all(const __u8 *id)
- 
- 	if (!sd.supports_dom) {
- 		printf("\t%-41s : No\n", "Optical diagnostics support");
--		return ;
-+		return;
- 	}
- 	printf("\t%-41s : Yes\n", "Optical diagnostics support");
- 
--#define PRINT_BIAS(string, index)                                        \
--	printf("\t%-41s : %.3f mA\n", (string),                          \
--	       (double)(sd.bias_cur[(index)] / 500.))
--
--# define PRINT_xX_PWR(string, var, index)                                \
--	printf("\t%-41s : %.4f mW / %.2f dBm\n", (string),               \
--	       (double)((var)[(index)] / 10000.),                        \
--	       convert_mw_to_dbm((double)((var)[(index)] / 10000.)))
--
--#define PRINT_TEMP(string, index)                                        \
--	printf("\t%-41s : %.2f degrees C / %.2f degrees F\n", (string),  \
--	       (double)(sd.sfp_temp[(index)] / 256.),                    \
--	       (double)(sd.sfp_temp[(index)] / 256. * 1.8 + 32.))
--
--#define PRINT_VCC(string, index)                                         \
--	printf("\t%-41s : %.4f V\n", (string),                           \
--	       (double)(sd.sfp_voltage[(index)] / 10000.))
--
--	PRINT_BIAS("Laser bias current", MCURR);
--	PRINT_xX_PWR("Laser output power", sd.tx_power, MCURR);
-+	PRINT_BIAS("Laser bias current", sd.bias_cur[MCURR]);
-+	PRINT_xX_PWR("Laser output power", sd.tx_power[MCURR]);
- 
- 	if (!sd.rx_power_type)
- 		rx_power_string = "Receiver signal OMA";
- 	else
- 		rx_power_string = "Receiver signal average optical power";
- 
--	PRINT_xX_PWR(rx_power_string, sd.rx_power, MCURR);
-+	PRINT_xX_PWR(rx_power_string, sd.rx_power[MCURR]);
- 
--	PRINT_TEMP("Module temperature", MCURR);
--	PRINT_VCC("Module voltage", MCURR);
-+	PRINT_TEMP("Module temperature", sd.sfp_temp[MCURR]);
-+	PRINT_VCC("Module voltage", sd.sfp_voltage[MCURR]);
- 
- 	printf("\t%-41s : %s\n", "Alarm/warning flags implemented",
- 	       (sd.supports_alarms ? "Yes" : "No"));
-@@ -323,40 +275,7 @@ void sff8472_show_all(const __u8 *id)
- 			       id[SFF_A2_BASE + sff8472_aw_flags[i].offset]
- 			       & sff8472_aw_flags[i].value ? "On" : "Off");
- 		}
--
--		PRINT_BIAS("Laser bias current high alarm threshold",   HALRM);
--		PRINT_BIAS("Laser bias current low alarm threshold",    LALRM);
--		PRINT_BIAS("Laser bias current high warning threshold", HWARN);
--		PRINT_BIAS("Laser bias current low warning threshold",  LWARN);
--
--		PRINT_xX_PWR("Laser output power high alarm threshold",
--			     sd.tx_power, HALRM);
--		PRINT_xX_PWR("Laser output power low alarm threshold",
--			     sd.tx_power, LALRM);
--		PRINT_xX_PWR("Laser output power high warning threshold",
--			     sd.tx_power, HWARN);
--		PRINT_xX_PWR("Laser output power low warning threshold",
--			     sd.tx_power, LWARN);
--
--		PRINT_TEMP("Module temperature high alarm threshold",   HALRM);
--		PRINT_TEMP("Module temperature low alarm threshold",    LALRM);
--		PRINT_TEMP("Module temperature high warning threshold", HWARN);
--		PRINT_TEMP("Module temperature low warning threshold",  LWARN);
--
--		PRINT_VCC("Module voltage high alarm threshold",   HALRM);
--		PRINT_VCC("Module voltage low alarm threshold",    LALRM);
--		PRINT_VCC("Module voltage high warning threshold", HWARN);
--		PRINT_VCC("Module voltage low warning threshold",  LWARN);
--
--		PRINT_xX_PWR("Laser rx power high alarm threshold",
--			     sd.rx_power, HALRM);
--		PRINT_xX_PWR("Laser rx power low alarm threshold",
--			     sd.rx_power, LALRM);
--		PRINT_xX_PWR("Laser rx power high warning threshold",
--			     sd.rx_power, HWARN);
--		PRINT_xX_PWR("Laser rx power low warning threshold",
--			     sd.rx_power, LWARN);
-+		sff_show_thresholds(sd);
- 	}
--
- }
- 
-diff --git a/sfpid.c b/sfpid.c
-index 0b5cd62..fd6415c 100644
---- a/sfpid.c
-+++ b/sfpid.c
-@@ -9,27 +9,11 @@
- 
- #include <stdio.h>
- #include "internal.h"
-+#include "sff-common.h"
- 
- static void sff8079_show_identifier(const __u8 *id)
- {
--	printf("\t%-41s : 0x%02x", "Identifier", id[0]);
--	switch (id[0]) {
--	case 0x00:
--		printf(" (no module present, unknown, or unspecified)\n");
--		break;
--	case 0x01:
--		printf(" (GBIC)\n");
--		break;
--	case 0x02:
--		printf(" (module soldered to motherboard)\n");
--		break;
--	case 0x03:
--		printf(" (SFP)\n");
--		break;
--	default:
--		 printf(" (reserved or unknown)\n");
--		break;
--	}
-+	sff8024_show_identifier(id, 0);
- }
- 
- static void sff8079_show_ext_identifier(const __u8 *id)
-@@ -47,60 +31,7 @@ static void sff8079_show_ext_identifier(const __u8 *id)
- 
- static void sff8079_show_connector(const __u8 *id)
- {
--	printf("\t%-41s : 0x%02x", "Connector", id[2]);
--	switch (id[2]) {
--	case 0x00:
--		printf(" (unknown or unspecified)\n");
--		break;
--	case 0x01:
--		printf(" (SC)\n");
--		break;
--	case 0x02:
--		printf(" (Fibre Channel Style 1 copper)\n");
--		break;
--	case 0x03:
--		printf(" (Fibre Channel Style 2 copper)\n");
--		break;
--	case 0x04:
--		printf(" (BNC/TNC)\n");
--		break;
--	case 0x05:
--		printf(" (Fibre Channel coaxial headers)\n");
--		break;
--	case 0x06:
--		printf(" (FibreJack)\n");
--		break;
--	case 0x07:
--		printf(" (LC)\n");
--		break;
--	case 0x08:
--		printf(" (MT-RJ)\n");
--		break;
--	case 0x09:
--		printf(" (MU)\n");
--		break;
--	case 0x0a:
--		printf(" (SG)\n");
--		break;
--	case 0x0b:
--		printf(" (Optical pigtail)\n");
--		break;
--	case 0x0c:
--		printf(" (MPO Parallel Optic)\n");
--		break;
--	case 0x20:
--		printf(" (HSSDC II)\n");
--		break;
--	case 0x21:
--		printf(" (Copper pigtail)\n");
--		break;
--	case 0x22:
--		printf(" (RJ45)\n");
--		break;
--	default:
--		printf(" (reserved or unknown)\n");
--		break;
--	}
-+	sff8024_show_connector(id, 2);
- }
- 
- static void sff8079_show_transceiver(const __u8 *id)
-@@ -241,33 +172,7 @@ static void sff8079_show_transceiver(const __u8 *id)
- 
- static void sff8079_show_encoding(const __u8 *id)
- {
--	printf("\t%-41s : 0x%02x", "Encoding", id[11]);
--	switch (id[11]) {
--	case 0x00:
--		printf(" (unspecified)\n");
--		break;
--	case 0x01:
--		printf(" (8B/10B)\n");
--		break;
--	case 0x02:
--		printf(" (4B/5B)\n");
--		break;
--	case 0x03:
--		printf(" (NRZ)\n");
--		break;
--	case 0x04:
--		printf(" (Manchester)\n");
--		break;
--	case 0x05:
--		printf(" (SONET Scrambled)\n");
--		break;
--	case 0x06:
--		printf(" (64B/66B)\n");
--		break;
--	default:
--		printf(" (reserved or unknown)\n");
--		break;
--	}
-+	sff8024_show_encoding(id, 11, ETH_MODULE_SFF_8472);
- }
- 
- static void sff8079_show_rate_identifier(const __u8 *id)
--- 
-1.8.3.1
-
diff --git a/SOURCES/0005-ethtool-QSFP-Plus-QSFP28-Diagnostics-Information-Sup.patch b/SOURCES/0005-ethtool-QSFP-Plus-QSFP28-Diagnostics-Information-Sup.patch
deleted file mode 100644
index a893134..0000000
--- a/SOURCES/0005-ethtool-QSFP-Plus-QSFP28-Diagnostics-Information-Sup.patch
+++ /dev/null
@@ -1,1466 +0,0 @@
-From 3cfd8329790e382c88c670e4f9e7014f1cbd4ad6 Mon Sep 17 00:00:00 2001
-From: Vidya Sagar Ravipati <vidya@cumulusnetworks.com>
-Date: Tue, 23 Aug 2016 06:30:32 -0700
-Subject: [PATCH 5/7] ethtool:QSFP Plus/QSFP28 Diagnostics Information Support
-
-This patch  provides following support
-a) Support for diagnostics information for QSFP Plus/QSFP28 modules
-   based on SFF-8436/SFF-8636
-
-Standards for QSFP+/QSFP28
-a) QSFP+/QSFP28 - SFF 8636 Rev 2.7 dated January 26,2016
-b) SFF-8024 Rev 4.0 dated May 31, 2016
-
-Signed-off-by: Vidya Sagar Ravipati <vidya@cumulusnetworks.com>
-Acked-by: Bert Kenward <bkenward@solarflare.com>
-Signed-off-by: John W. Linville <linville@tuxdriver.com>
-(cherry picked from commit a5e73bb05ee4de0a1c06b117e0ee3ea4cba83561)
----
- Makefile.am |   2 +-
- ethtool.c   |   5 +
- internal.h  |   3 +
- qsfp.c      | 788 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- qsfp.h      | 595 +++++++++++++++++++++++++++++++++++++++++++++
- 5 files changed, 1392 insertions(+), 1 deletion(-)
- create mode 100644 qsfp.c
- create mode 100644 qsfp.h
-
-diff --git a/Makefile.am b/Makefile.am
-index 3c9f387..de2db2e 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -14,7 +14,7 @@ ethtool_SOURCES += \
- 		  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
-+		  ixgbevf.c tse.c vmxnet3.c qsfp.c qsfp.h
- endif
- 
- TESTS = test-cmdline test-features
-diff --git a/ethtool.c b/ethtool.c
-index 796d0b5..ffb3573 100644
---- a/ethtool.c
-+++ b/ethtool.c
-@@ -4355,6 +4355,11 @@ static int do_getmodule(struct cmd_context *ctx)
- 				sff8079_show_all(eeprom->data);
- 				sff8472_show_all(eeprom->data);
- 				break;
-+			case ETH_MODULE_SFF_8436:
-+			case ETH_MODULE_SFF_8636:
-+				sff8636_show_all(eeprom->data,
-+						 modinfo.eeprom_len);
-+				break;
- #endif
- 			default:
- 				geeprom_dump_hex = 1;
-diff --git a/internal.h b/internal.h
-index ef27ab2..3c08b74 100644
---- a/internal.h
-+++ b/internal.h
-@@ -345,4 +345,7 @@ void sff8079_show_all(const __u8 *id);
- /* Optics diagnostics */
- void sff8472_show_all(const __u8 *id);
- 
-+/* QSFP Optics diagnostics */
-+void sff8636_show_all(const __u8 *id, __u32 eeprom_len);
-+
- #endif /* ETHTOOL_INTERNAL_H__ */
-diff --git a/qsfp.c b/qsfp.c
-new file mode 100644
-index 0000000..213802e
---- /dev/null
-+++ b/qsfp.c
-@@ -0,0 +1,788 @@
-+/*
-+ * qsfp.c: Implements SFF-8636 based QSFP+/QSFP28 Diagnostics Memory map.
-+ *
-+ * Copyright 2010 Solarflare Communications Inc.
-+ * Aurelien Guillaume <aurelien@iwi.me> (C) 2012
-+ * Copyright (C) 2014 Cumulus networks Inc.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Freeoftware Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ *  Vidya Ravipati <vidya@cumulusnetworks.com>
-+ *   This implementation is loosely based on current SFP parser
-+ *   and SFF-8636 spec Rev 2.7 (ftp://ftp.seagate.com/pub/sff/SFF-8636.PDF)
-+ *   by SFF Committee.
-+ */
-+
-+/*
-+ *	Description:
-+ *	a) The register/memory layout is up to 5 128 byte pages defined by
-+ *		a "pages valid" register and switched via a "page select"
-+ *		register. Memory of 256 bytes can be memory mapped at a time
-+ *		according to SFF 8636.
-+ *	b) SFF 8636 based 640 bytes memory layout is presented for parser
-+ *
-+ *           SFF 8636 based QSFP Memory Map
-+ *
-+ *           2-Wire Serial Address: 1010000x
-+ *
-+ *           Lower Page 00h (128 bytes)
-+ *           ======================
-+ *           |                     |
-+ *           |Page Select Byte(127)|
-+ *           ======================
-+ *                    |
-+ *                    V
-+ *	     ----------------------------------------
-+ *	    |             |            |             |
-+ *	    V             V            V             V
-+ *	 ----------   ----------   ---------    ------------
-+ *	| Upper    | | Upper    | | Upper    | | Upper      |
-+ *	| Page 00h | | Page 01h | | Page 02h | | Page 03h   |
-+ *	|          | |(Optional)| |(Optional)| | (Optional) |
-+ *	|          | |          | |          | |            |
-+ *	|          | |          | |          | |            |
-+ *	|    ID    | |   AST    | |  User    | |  For       |
-+ *	|  Fields  | |  Table   | | EEPROM   | |  Cable     |
-+ *	|          | |          | | Data     | | Assemblies |
-+ *	|          | |          | |          | |            |
-+ *	|          | |          | |          | |            |
-+ *	-----------  -----------   ----------  --------------
-+ *
-+ *
-+ **/
-+#include <stdio.h>
-+#include <math.h>
-+#include "internal.h"
-+#include "sff-common.h"
-+#include "qsfp.h"
-+
-+#define MAX_DESC_SIZE	42
-+
-+static struct sff8636_aw_flags {
-+	const char *str;        /* Human-readable string, null at the end */
-+	int offset;             /* A2-relative address offset */
-+	__u8 value;             /* Alarm is on if (offset & value) != 0. */
-+} sff8636_aw_flags[] = {
-+	{ "Laser bias current high alarm   (Chan 1)",
-+		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_1_HALARM) },
-+	{ "Laser bias current low alarm    (Chan 1)",
-+		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_1_LALARM) },
-+	{ "Laser bias current high warning (Chan 1)",
-+		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_1_HWARN) },
-+	{ "Laser bias current low warning  (Chan 1)",
-+		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_1_LWARN) },
-+
-+	{ "Laser bias current high alarm   (Chan 2)",
-+		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_2_HALARM) },
-+	{ "Laser bias current low alarm    (Chan 2)",
-+		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_2_LALARM) },
-+	{ "Laser bias current high warning (Chan 2)",
-+		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_2_HWARN) },
-+	{ "Laser bias current low warning  (Chan 2)",
-+		SFF8636_TX_BIAS_12_AW_OFFSET, (SFF8636_TX_BIAS_2_LWARN) },
-+
-+	{ "Laser bias current high alarm   (Chan 3)",
-+		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_3_HALARM) },
-+	{ "Laser bias current low alarm    (Chan 3)",
-+		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_3_LALARM) },
-+	{ "Laser bias current high warning (Chan 3)",
-+		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_3_HWARN) },
-+	{ "Laser bias current low warning  (Chan 3)",
-+		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_3_LWARN) },
-+
-+	{ "Laser bias current high alarm   (Chan 4)",
-+		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_4_HALARM) },
-+	{ "Laser bias current low alarm    (Chan 4)",
-+		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_4_LALARM) },
-+	{ "Laser bias current high warning (Chan 4)",
-+		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_4_HWARN) },
-+	{ "Laser bias current low warning  (Chan 4)",
-+		SFF8636_TX_BIAS_34_AW_OFFSET, (SFF8636_TX_BIAS_4_LWARN) },
-+
-+	{ "Module temperature high alarm",
-+		SFF8636_TEMP_AW_OFFSET, (SFF8636_TEMP_HALARM_STATUS) },
-+	{ "Module temperature low alarm",
-+		SFF8636_TEMP_AW_OFFSET, (SFF8636_TEMP_LALARM_STATUS) },
-+	{ "Module temperature high warning",
-+		SFF8636_TEMP_AW_OFFSET, (SFF8636_TEMP_HWARN_STATUS) },
-+	{ "Module temperature low warning",
-+		SFF8636_TEMP_AW_OFFSET, (SFF8636_TEMP_LWARN_STATUS) },
-+
-+	{ "Module voltage high alarm",
-+		SFF8636_VCC_AW_OFFSET, (SFF8636_VCC_HALARM_STATUS) },
-+	{ "Module voltage low alarm",
-+		SFF8636_VCC_AW_OFFSET, (SFF8636_VCC_LALARM_STATUS) },
-+	{ "Module voltage high warning",
-+		SFF8636_VCC_AW_OFFSET, (SFF8636_VCC_HWARN_STATUS) },
-+	{ "Module voltage low warning",
-+		SFF8636_VCC_AW_OFFSET, (SFF8636_VCC_LWARN_STATUS) },
-+
-+	{ "Laser tx power high alarm   (Channel 1)",
-+		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_1_HALARM) },
-+	{ "Laser tx power low alarm    (Channel 1)",
-+		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_1_LALARM) },
-+	{ "Laser tx power high warning (Channel 1)",
-+		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_1_HWARN) },
-+	{ "Laser tx power low warning  (Channel 1)",
-+		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_1_LWARN) },
-+
-+	{ "Laser tx power high alarm   (Channel 2)",
-+		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_2_HALARM) },
-+	{ "Laser tx power low alarm    (Channel 2)",
-+		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_2_LALARM) },
-+	{ "Laser tx power high warning (Channel 2)",
-+		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_2_HWARN) },
-+	{ "Laser tx power low warning  (Channel 2)",
-+		SFF8636_TX_PWR_12_AW_OFFSET, (SFF8636_TX_PWR_2_LWARN) },
-+
-+	{ "Laser tx power high alarm   (Channel 3)",
-+		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_3_HALARM) },
-+	{ "Laser tx power low alarm    (Channel 3)",
-+		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_3_LALARM) },
-+	{ "Laser tx power high warning (Channel 3)",
-+		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_3_HWARN) },
-+	{ "Laser tx power low warning  (Channel 3)",
-+		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_3_LWARN) },
-+
-+	{ "Laser tx power high alarm   (Channel 4)",
-+		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_4_HALARM) },
-+	{ "Laser tx power low alarm    (Channel 4)",
-+		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_4_LALARM) },
-+	{ "Laser tx power high warning (Channel 4)",
-+		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_4_HWARN) },
-+	{ "Laser tx power low warning  (Channel 4)",
-+		SFF8636_TX_PWR_34_AW_OFFSET, (SFF8636_TX_PWR_4_LWARN) },
-+
-+	{ "Laser rx power high alarm   (Channel 1)",
-+		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_1_HALARM) },
-+	{ "Laser rx power low alarm    (Channel 1)",
-+		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_1_LALARM) },
-+	{ "Laser rx power high warning (Channel 1)",
-+		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_1_HWARN) },
-+	{ "Laser rx power low warning  (Channel 1)",
-+		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_1_LWARN) },
-+
-+	{ "Laser rx power high alarm   (Channel 2)",
-+		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_2_HALARM) },
-+	{ "Laser rx power low alarm    (Channel 2)",
-+		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_2_LALARM) },
-+	{ "Laser rx power high warning (Channel 2)",
-+		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_2_HWARN) },
-+	{ "Laser rx power low warning  (Channel 2)",
-+		SFF8636_RX_PWR_12_AW_OFFSET, (SFF8636_RX_PWR_2_LWARN) },
-+
-+	{ "Laser rx power high alarm   (Channel 3)",
-+		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_3_HALARM) },
-+	{ "Laser rx power low alarm    (Channel 3)",
-+		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_3_LALARM) },
-+	{ "Laser rx power high warning (Channel 3)",
-+		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_3_HWARN) },
-+	{ "Laser rx power low warning  (Channel 3)",
-+		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_3_LWARN) },
-+
-+	{ "Laser rx power high alarm   (Channel 4)",
-+		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_4_HALARM) },
-+	{ "Laser rx power low alarm    (Channel 4)",
-+		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_4_LALARM) },
-+	{ "Laser rx power high warning (Channel 4)",
-+		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_4_HWARN) },
-+	{ "Laser rx power low warning  (Channel 4)",
-+		SFF8636_RX_PWR_34_AW_OFFSET, (SFF8636_RX_PWR_4_LWARN) },
-+
-+	{ NULL, 0, 0 },
-+};
-+
-+static void sff8636_show_identifier(const __u8 *id)
-+{
-+	sff8024_show_identifier(id, SFF8636_ID_OFFSET);
-+}
-+
-+static void sff8636_show_ext_identifier(const __u8 *id)
-+{
-+	printf("\t%-41s : 0x%02x\n", "Extended identifier",
-+			id[SFF8636_EXT_ID_OFFSET]);
-+
-+	static const char *pfx =
-+		"\tExtended identifier description           :";
-+
-+	switch (id[SFF8636_EXT_ID_OFFSET] & SFF8636_EXT_ID_PWR_CLASS_MASK) {
-+	case SFF8636_EXT_ID_PWR_CLASS_1:
-+		printf("%s 1.5W max. Power consumption\n", pfx);
-+		break;
-+	case SFF8636_EXT_ID_PWR_CLASS_2:
-+		printf("%s 2.0W max. Power consumption\n", pfx);
-+		break;
-+	case SFF8636_EXT_ID_PWR_CLASS_3:
-+		printf("%s 2.5W max. Power consumption\n", pfx);
-+		break;
-+	case SFF8636_EXT_ID_PWR_CLASS_4:
-+		printf("%s 3.5W max. Power consumption\n", pfx);
-+		break;
-+	}
-+
-+	if (id[SFF8636_EXT_ID_OFFSET] & SFF8636_EXT_ID_CDR_TX_MASK)
-+		printf("%s CDR present in TX,", pfx);
-+	else
-+		printf("%s No CDR in TX,", pfx);
-+
-+	if (id[SFF8636_EXT_ID_OFFSET] & SFF8636_EXT_ID_CDR_RX_MASK)
-+		printf(" CDR present in RX\n");
-+	else
-+		printf(" No CDR in RX\n");
-+
-+	switch (id[SFF8636_EXT_ID_OFFSET] & SFF8636_EXT_ID_EPWR_CLASS_MASK) {
-+	case SFF8636_EXT_ID_PWR_CLASS_LEGACY:
-+		printf("%s", pfx);
-+		break;
-+	case SFF8636_EXT_ID_PWR_CLASS_5:
-+		printf("%s 4.0W max. Power consumption,", pfx);
-+		break;
-+	case SFF8636_EXT_ID_PWR_CLASS_6:
-+		printf("%s 4.5W max. Power consumption, ", pfx);
-+		break;
-+	case SFF8636_EXT_ID_PWR_CLASS_7:
-+		printf("%s 5.0W max. Power consumption, ", pfx);
-+		break;
-+	}
-+	if (id[SFF8636_PWR_MODE_OFFSET] & SFF8636_HIGH_PWR_ENABLE)
-+		printf(" High Power Class (> 3.5 W) enabled\n");
-+	else
-+		printf(" High Power Class (> 3.5 W) not enabled\n");
-+}
-+
-+static void sff8636_show_connector(const __u8 *id)
-+{
-+	sff8024_show_connector(id, SFF8636_CTOR_OFFSET);
-+}
-+
-+static void sff8636_show_transceiver(const __u8 *id)
-+{
-+	static const char *pfx =
-+		"\tTransceiver type                          :";
-+
-+	printf("\t%-41s : 0x%02x 0x%02x 0x%02x " \
-+			"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
-+			"Transceiver codes",
-+			id[SFF8636_ETHERNET_COMP_OFFSET],
-+			id[SFF8636_SONET_COMP_OFFSET],
-+			id[SFF8636_SAS_COMP_OFFSET],
-+			id[SFF8636_GIGE_COMP_OFFSET],
-+			id[SFF8636_FC_LEN_OFFSET],
-+			id[SFF8636_FC_TECH_OFFSET],
-+			id[SFF8636_FC_TRANS_MEDIA_OFFSET],
-+			id[SFF8636_FC_SPEED_OFFSET]);
-+
-+	/* 10G/40G Ethernet Compliance Codes */
-+	if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_10G_LRM)
-+		printf("%s 10G Ethernet: 10G Base-LRM\n", pfx);
-+	if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_10G_LR)
-+		printf("%s 10G Ethernet: 10G Base-LR\n", pfx);
-+	if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_10G_SR)
-+		printf("%s 10G Ethernet: 10G Base-SR\n", pfx);
-+	if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_40G_CR4)
-+		printf("%s 40G Ethernet: 40G Base-CR4\n", pfx);
-+	if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_40G_SR4)
-+		printf("%s 40G Ethernet: 40G Base-SR4\n", pfx);
-+	if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_40G_LR4)
-+		printf("%s 40G Ethernet: 40G Base-LR4\n", pfx);
-+	if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_40G_ACTIVE)
-+		printf("%s 40G Ethernet: 40G Active Cable (XLPPI)\n", pfx);
-+	/* Extended Specification Compliance Codes from SFF-8024 */
-+	if (id[SFF8636_ETHERNET_COMP_OFFSET] & SFF8636_ETHERNET_RSRVD) {
-+		switch (id[SFF8636_OPTION_1_OFFSET]) {
-+		case SFF8636_ETHERNET_UNSPECIFIED:
-+			printf("%s (reserved or unknown)\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_AOC:
-+			printf("%s 100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 5x10^(-5)\n",
-+					pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_SR4:
-+			printf("%s 100G Ethernet: 100G Base-SR4 or 25GBase-SR\n",
-+					pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_LR4:
-+			printf("%s 100G Ethernet: 100G Base-LR4\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_ER4:
-+			printf("%s 100G Ethernet: 100G Base-ER4\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_SR10:
-+			printf("%s 100G Ethernet: 100G Base-SR10\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_CWDM4_FEC:
-+			printf("%s 100G Ethernet: 100G CWDM4 MSA with FEC\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_PSM4:
-+			printf("%s 100G Ethernet: 100G PSM4 Parallel SMF\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_ACC:
-+			printf("%s 100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 5x10^(-5)\n",
-+				pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_CWDM4_NO_FEC:
-+			printf("%s 100G Ethernet: 100G CWDM4 MSA without FEC\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_RSVD1:
-+			printf("%s (reserved or unknown)\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_CR4:
-+			printf("%s 100G Ethernet: 100G Base-CR4 or 25G Base-CR CA-L\n",
-+				pfx);
-+			break;
-+		case SFF8636_ETHERNET_25G_CR_CA_S:
-+			printf("%s 25G Ethernet: 25G Base-CR CA-S\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_25G_CR_CA_N:
-+			printf("%s 25G Ethernet: 25G Base-CR CA-N\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_40G_ER4:
-+			printf("%s 40G Ethernet: 40G Base-ER4\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_4X10_SR:
-+			printf("%s 4x10G Ethernet: 10G Base-SR\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_40G_PSM4:
-+			printf("%s 40G Ethernet: 40G PSM4 Parallel SMF\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_G959_P1I1_2D1:
-+			printf("%s Ethernet: G959.1 profile P1I1-2D1 (10709 MBd, 2km, 1310nm SM)\n",
-+					pfx);
-+			break;
-+		case SFF8636_ETHERNET_G959_P1S1_2D2:
-+			printf("%s Ethernet: G959.1 profile P1S1-2D2 (10709 MBd, 40km, 1550nm SM)\n",
-+					pfx);
-+			break;
-+		case SFF8636_ETHERNET_G959_P1L1_2D2:
-+			printf("%s Ethernet: G959.1 profile P1L1-2D2 (10709 MBd, 80km, 1550nm SM)\n",
-+					pfx);
-+			break;
-+		case SFF8636_ETHERNET_10GT_SFI:
-+			printf("%s 10G Ethernet: 10G Base-T with SFI electrical interface\n",
-+					pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_CLR4:
-+			printf("%s 100G Ethernet: 100G CLR4\n", pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_AOC2:
-+			printf("%s 100G Ethernet: 100G AOC or 25GAUI C2M AOC with worst BER of 10^(-12)\n",
-+					pfx);
-+			break;
-+		case SFF8636_ETHERNET_100G_ACC2:
-+			printf("%s 100G Ethernet: 100G ACC or 25GAUI C2M ACC with worst BER of 10^(-12)\n",
-+					pfx);
-+			break;
-+		default:
-+			printf("%s (reserved or unknown)\n", pfx);
-+			break;
-+		}
-+	}
-+
-+	/* SONET Compliance Codes */
-+	if (id[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_40G_OTN))
-+		printf("%s 40G OTN (OTU3B/OTU3C)\n", pfx);
-+	if (id[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_OC48_LR))
-+		printf("%s SONET: OC-48, long reach\n", pfx);
-+	if (id[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_OC48_IR))
-+		printf("%s SONET: OC-48, intermediate reach\n", pfx);
-+	if (id[SFF8636_SONET_COMP_OFFSET] & (SFF8636_SONET_OC48_SR))
-+		printf("%s SONET: OC-48, short reach\n", pfx);
-+
-+	/* SAS/SATA Compliance Codes */
-+	if (id[SFF8636_SAS_COMP_OFFSET] & (SFF8636_SAS_6G))
-+		printf("%s SAS 6.0G\n", pfx);
-+	if (id[SFF8636_SAS_COMP_OFFSET] & (SFF8636_SAS_3G))
-+		printf("%s SAS 3.0G\n", pfx);
-+
-+	/* Ethernet Compliance Codes */
-+	if (id[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_T)
-+		printf("%s Ethernet: 1000BASE-T\n", pfx);
-+	if (id[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_CX)
-+		printf("%s Ethernet: 1000BASE-CX\n", pfx);
-+	if (id[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_LX)
-+		printf("%s Ethernet: 1000BASE-LX\n", pfx);
-+	if (id[SFF8636_GIGE_COMP_OFFSET] & SFF8636_GIGE_1000_BASE_SX)
-+		printf("%s Ethernet: 1000BASE-SX\n", pfx);
-+
-+	/* Fibre Channel link length */
-+	if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_VERY_LONG)
-+		printf("%s FC: very long distance (V)\n", pfx);
-+	if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_SHORT)
-+		printf("%s FC: short distance (S)\n", pfx);
-+	if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_INT)
-+		printf("%s FC: intermediate distance (I)\n", pfx);
-+	if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_LONG)
-+		printf("%s FC: long distance (L)\n", pfx);
-+	if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_LEN_MED)
-+		printf("%s FC: medium distance (M)\n", pfx);
-+
-+	/* Fibre Channel transmitter technology */
-+	if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_TECH_LONG_LC)
-+		printf("%s FC: Longwave laser (LC)\n", pfx);
-+	if (id[SFF8636_FC_LEN_OFFSET] & SFF8636_FC_TECH_ELEC_INTER)
-+		printf("%s FC: Electrical inter-enclosure (EL)\n", pfx);
-+	if (id[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_ELEC_INTRA)
-+		printf("%s FC: Electrical intra-enclosure (EL)\n", pfx);
-+	if (id[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_SHORT_WO_OFC)
-+		printf("%s FC: Shortwave laser w/o OFC (SN)\n", pfx);
-+	if (id[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_SHORT_W_OFC)
-+		printf("%s FC: Shortwave laser with OFC (SL)\n", pfx);
-+	if (id[SFF8636_FC_TECH_OFFSET] & SFF8636_FC_TECH_LONG_LL)
-+		printf("%s FC: Longwave laser (LL)\n", pfx);
-+
-+	/* Fibre Channel transmission media */
-+	if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_TW)
-+		printf("%s FC: Twin Axial Pair (TW)\n", pfx);
-+	if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_TP)
-+		printf("%s FC: Twisted Pair (TP)\n", pfx);
-+	if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_MI)
-+		printf("%s FC: Miniature Coax (MI)\n", pfx);
-+	if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_TV)
-+		printf("%s FC: Video Coax (TV)\n", pfx);
-+	if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_M6)
-+		printf("%s FC: Multimode, 62.5m (M6)\n", pfx);
-+	if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_M5)
-+		printf("%s FC: Multimode, 50m (M5)\n", pfx);
-+	if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_OM3)
-+		printf("%s FC: Multimode, 50um (OM3)\n", pfx);
-+	if (id[SFF8636_FC_TRANS_MEDIA_OFFSET] & SFF8636_FC_TRANS_MEDIA_SM)
-+		printf("%s FC: Single Mode (SM)\n", pfx);
-+
-+	/* Fibre Channel speed */
-+	if (id[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_1200_MBPS)
-+		printf("%s FC: 1200 MBytes/sec\n", pfx);
-+	if (id[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_800_MBPS)
-+		printf("%s FC: 800 MBytes/sec\n", pfx);
-+	if (id[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_1600_MBPS)
-+		printf("%s FC: 1600 MBytes/sec\n", pfx);
-+	if (id[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_400_MBPS)
-+		printf("%s FC: 400 MBytes/sec\n", pfx);
-+	if (id[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_200_MBPS)
-+		printf("%s FC: 200 MBytes/sec\n", pfx);
-+	if (id[SFF8636_FC_SPEED_OFFSET] & SFF8636_FC_SPEED_100_MBPS)
-+		printf("%s FC: 100 MBytes/sec\n", pfx);
-+}
-+
-+static void sff8636_show_encoding(const __u8 *id)
-+{
-+	sff8024_show_encoding(id, SFF8636_ENCODING_OFFSET, ETH_MODULE_SFF_8636);
-+}
-+
-+static void sff8636_show_rate_identifier(const __u8 *id)
-+{
-+	/* TODO: Need to fix rate select logic */
-+	printf("\t%-41s : 0x%02x\n", "Rate identifier",
-+			id[SFF8636_EXT_RS_OFFSET]);
-+}
-+
-+static void sff8636_show_oui(const __u8 *id)
-+{
-+	sff8024_show_oui(id, SFF8636_VENDOR_OUI_OFFSET);
-+}
-+
-+static void sff8636_show_wavelength_or_copper_compliance(const __u8 *id)
-+{
-+	printf("\t%-41s : 0x%02x", "Transmitter technology",
-+		(id[SFF8636_DEVICE_TECH_OFFSET] & SFF8636_TRANS_TECH_MASK));
-+
-+	switch (id[SFF8636_DEVICE_TECH_OFFSET] & SFF8636_TRANS_TECH_MASK) {
-+	case SFF8636_TRANS_850_VCSEL:
-+		printf(" (850 nm VCSEL)\n");
-+		break;
-+	case SFF8636_TRANS_1310_VCSEL:
-+		printf(" (1310 nm VCSEL)\n");
-+		break;
-+	case SFF8636_TRANS_1550_VCSEL:
-+		printf(" (1550 nm VCSEL)\n");
-+		break;
-+	case SFF8636_TRANS_1310_FP:
-+		printf(" (1310 nm FP)\n");
-+		break;
-+	case SFF8636_TRANS_1310_DFB:
-+		printf(" (1310 nm DFB)\n");
-+		break;
-+	case SFF8636_TRANS_1550_DFB:
-+		printf(" (1550 nm DFB)\n");
-+		break;
-+	case SFF8636_TRANS_1310_EML:
-+		printf(" (1310 nm EML)\n");
-+		break;
-+	case SFF8636_TRANS_1550_EML:
-+		printf(" (1550 nm EML)\n");
-+		break;
-+	case SFF8636_TRANS_OTHERS:
-+		printf(" (Others/Undefined)\n");
-+		break;
-+	case SFF8636_TRANS_1490_DFB:
-+		printf(" (1490 nm DFB)\n");
-+		break;
-+	case SFF8636_TRANS_COPPER_PAS_UNEQUAL:
-+		printf(" (Copper cable unequalized)\n");
-+		break;
-+	case SFF8636_TRANS_COPPER_PAS_EQUAL:
-+		printf(" (Copper cable passive equalized)\n");
-+		break;
-+	case SFF8636_TRANS_COPPER_LNR_FAR_EQUAL:
-+		printf(" (Copper cable, near and far end limiting active equalizers)\n");
-+		break;
-+	case SFF8636_TRANS_COPPER_FAR_EQUAL:
-+		printf(" (Copper cable, far end limiting active equalizers)\n");
-+		break;
-+	case SFF8636_TRANS_COPPER_NEAR_EQUAL:
-+		printf(" (Copper cable, near end limiting active equalizers)\n");
-+		break;
-+	case SFF8636_TRANS_COPPER_LNR_EQUAL:
-+		printf(" (Copper cable, linear active equalizers)\n");
-+		break;
-+	}
-+
-+	if ((id[SFF8636_DEVICE_TECH_OFFSET] & SFF8636_TRANS_TECH_MASK)
-+			>= SFF8636_TRANS_COPPER_PAS_UNEQUAL) {
-+		printf("\t%-41s : %udb\n", "Attenuation at 2.5GHz",
-+			id[SFF8636_WAVELEN_HIGH_BYTE_OFFSET]);
-+		printf("\t%-41s : %udb\n", "Attenuation at 5.0GHz",
-+			id[SFF8636_WAVELEN_LOW_BYTE_OFFSET]);
-+		printf("\t%-41s : %udb\n", "Attenuation at 7.0GHz",
-+			id[SFF8636_WAVE_TOL_HIGH_BYTE_OFFSET]);
-+		printf("\t%-41s : %udb\n", "Attenuation at 12.9GHz",
-+			id[SFF8636_WAVE_TOL_LOW_BYTE_OFFSET]);
-+	} else {
-+		printf("\t%-41s : %.3lfnm\n", "Laser wavelength",
-+			(((id[SFF8636_WAVELEN_HIGH_BYTE_OFFSET] << 8) |
-+				id[SFF8636_WAVELEN_LOW_BYTE_OFFSET])*0.05));
-+		printf("\t%-41s : %.3lfnm\n", "Laser wavelength tolerance",
-+			(((id[SFF8636_WAVE_TOL_HIGH_BYTE_OFFSET] << 8) |
-+			id[SFF8636_WAVE_TOL_LOW_BYTE_OFFSET])*0.005));
-+	}
-+}
-+
-+static void sff8636_show_revision_compliance(const __u8 *id)
-+{
-+	static const char *pfx =
-+		"\tRevision Compliance                       :";
-+
-+	switch (id[SFF8636_REV_COMPLIANCE_OFFSET]) {
-+	case SFF8636_REV_UNSPECIFIED:
-+		printf("%s Revision not specified\n", pfx);
-+		break;
-+	case SFF8636_REV_8436_48:
-+		printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx);
-+		break;
-+	case SFF8636_REV_8436_8636:
-+		printf("%s SFF-8436 Rev 4.8 or earlier\n", pfx);
-+		break;
-+	case SFF8636_REV_8636_13:
-+		printf("%s SFF-8636 Rev 1.3 or earlier\n", pfx);
-+		break;
-+	case SFF8636_REV_8636_14:
-+		printf("%s SFF-8636 Rev 1.4\n", pfx);
-+		break;
-+	case SFF8636_REV_8636_15:
-+		printf("%s SFF-8636 Rev 1.5\n", pfx);
-+		break;
-+	case SFF8636_REV_8636_20:
-+		printf("%s SFF-8636 Rev 2.0\n", pfx);
-+		break;
-+	case SFF8636_REV_8636_27:
-+		printf("%s SFF-8636 Rev 2.5/2.6/2.7\n", pfx);
-+		break;
-+	default:
-+		printf("%s Unallocated\n", pfx);
-+		break;
-+	}
-+}
-+
-+/*
-+ * 2-byte internal temperature conversions:
-+ * First byte is a signed 8-bit integer, which is the temp decimal part
-+ * Second byte are 1/256th of degree, which are added to the dec part.
-+ */
-+#define SFF8636_OFFSET_TO_TEMP(offset) ((__s16)OFFSET_TO_U16(offset))
-+
-+static void sff8636_dom_parse(const __u8 *id, struct sff_diags *sd)
-+{
-+	int i = 0;
-+
-+	/* Monitoring Thresholds for Alarms and Warnings */
-+	sd->sfp_voltage[MCURR] = OFFSET_TO_U16(SFF8636_VCC_CURR);
-+	sd->sfp_voltage[HALRM] = OFFSET_TO_U16(SFF8636_VCC_HALRM);
-+	sd->sfp_voltage[LALRM] = OFFSET_TO_U16(SFF8636_VCC_LALRM);
-+	sd->sfp_voltage[HWARN] = OFFSET_TO_U16(SFF8636_VCC_HWARN);
-+	sd->sfp_voltage[LWARN] = OFFSET_TO_U16(SFF8636_VCC_LWARN);
-+
-+	sd->sfp_temp[MCURR] = SFF8636_OFFSET_TO_TEMP(SFF8636_TEMP_CURR);
-+	sd->sfp_temp[HALRM] = SFF8636_OFFSET_TO_TEMP(SFF8636_TEMP_HALRM);
-+	sd->sfp_temp[LALRM] = SFF8636_OFFSET_TO_TEMP(SFF8636_TEMP_LALRM);
-+	sd->sfp_temp[HWARN] = SFF8636_OFFSET_TO_TEMP(SFF8636_TEMP_HWARN);
-+	sd->sfp_temp[LWARN] = SFF8636_OFFSET_TO_TEMP(SFF8636_TEMP_LWARN);
-+
-+	sd->bias_cur[HALRM] = OFFSET_TO_U16(SFF8636_TX_BIAS_HALRM);
-+	sd->bias_cur[LALRM] = OFFSET_TO_U16(SFF8636_TX_BIAS_LALRM);
-+	sd->bias_cur[HWARN] = OFFSET_TO_U16(SFF8636_TX_BIAS_HWARN);
-+	sd->bias_cur[LWARN] = OFFSET_TO_U16(SFF8636_TX_BIAS_LWARN);
-+
-+	sd->tx_power[HALRM] = OFFSET_TO_U16(SFF8636_TX_PWR_HALRM);
-+	sd->tx_power[LALRM] = OFFSET_TO_U16(SFF8636_TX_PWR_LALRM);
-+	sd->tx_power[HWARN] = OFFSET_TO_U16(SFF8636_TX_PWR_HWARN);
-+	sd->tx_power[LWARN] = OFFSET_TO_U16(SFF8636_TX_PWR_LWARN);
-+
-+	sd->rx_power[HALRM] = OFFSET_TO_U16(SFF8636_RX_PWR_HALRM);
-+	sd->rx_power[LALRM] = OFFSET_TO_U16(SFF8636_RX_PWR_LALRM);
-+	sd->rx_power[HWARN] = OFFSET_TO_U16(SFF8636_RX_PWR_HWARN);
-+	sd->rx_power[LWARN] = OFFSET_TO_U16(SFF8636_RX_PWR_LWARN);
-+
-+
-+	/* Channel Specific Data */
-+	for (i = 0; i < MAX_CHANNEL_NUM; i++) {
-+		u8 rx_power_offset, tx_bias_offset;
-+		u8 tx_power_offset;
-+
-+		switch (i) {
-+		case 0:
-+			rx_power_offset = SFF8636_RX_PWR_1_OFFSET;
-+			tx_power_offset = SFF8636_TX_PWR_1_OFFSET;
-+			tx_bias_offset = SFF8636_TX_BIAS_1_OFFSET;
-+			break;
-+		case 1:
-+			rx_power_offset = SFF8636_RX_PWR_2_OFFSET;
-+			tx_power_offset = SFF8636_TX_PWR_2_OFFSET;
-+			tx_bias_offset = SFF8636_TX_BIAS_2_OFFSET;
-+			break;
-+		case 2:
-+			rx_power_offset = SFF8636_RX_PWR_3_OFFSET;
-+			tx_power_offset = SFF8636_TX_PWR_3_OFFSET;
-+			tx_bias_offset = SFF8636_TX_BIAS_3_OFFSET;
-+			break;
-+		case 3:
-+			rx_power_offset = SFF8636_RX_PWR_4_OFFSET;
-+			tx_power_offset = SFF8636_TX_PWR_4_OFFSET;
-+			tx_bias_offset = SFF8636_TX_BIAS_4_OFFSET;
-+			break;
-+		default:
-+			printf(" Invalid channel: %d\n", i);
-+			break;
-+		}
-+		sd->scd[i].bias_cur = OFFSET_TO_U16(tx_bias_offset);
-+		sd->scd[i].rx_power = OFFSET_TO_U16(rx_power_offset);
-+		sd->scd[i].tx_power = OFFSET_TO_U16(tx_power_offset);
-+	}
-+
-+}
-+
-+static void sff8636_show_dom(const __u8 *id, __u32 eeprom_len)
-+{
-+	struct sff_diags sd;
-+	char *rx_power_string = NULL;
-+	char power_string[MAX_DESC_SIZE];
-+	int i;
-+
-+	/*
-+	 * There is no clear identifier to signify the existence of
-+	 * optical diagnostics similar to SFF-8472. So checking existence
-+	 * of page 3, will provide the gurantee for existence of alarms
-+	 * and thresholds
-+	 * If pagging support exists, then supports_alarms is marked as 1
-+	 */
-+
-+	if (eeprom_len == ETH_MODULE_SFF_8636_MAX_LEN) {
-+		if (!(id[SFF8636_STATUS_2_OFFSET] &
-+					SFF8636_STATUS_PAGE_3_PRESENT)) {
-+			sd.supports_alarms = 1;
-+		}
-+	}
-+
-+	sd.rx_power_type = id[SFF8636_DIAG_TYPE_OFFSET] &
-+						SFF8636_RX_PWR_TYPE_MASK;
-+	sd.tx_power_type = id[SFF8636_DIAG_TYPE_OFFSET] &
-+						SFF8636_RX_PWR_TYPE_MASK;
-+
-+	sff8636_dom_parse(id, &sd);
-+
-+	PRINT_TEMP("Module temperature", sd.sfp_temp[MCURR]);
-+	PRINT_VCC("Module voltage", sd.sfp_voltage[MCURR]);
-+
-+	/*
-+	 * SFF-8636/8436 spec is not clear whether RX power/ TX bias
-+	 * current fields are supported or not. A valid temperature
-+	 * reading is used as existence for TX/RX power.
-+	 */
-+	if ((sd.sfp_temp[MCURR] == 0x0) || (sd.sfp_temp[MCURR] == 0xFFFF))
-+		return;
-+
-+	printf("\t%-41s : %s\n", "Alarm/warning flags implemented",
-+		(sd.supports_alarms ? "Yes" : "No"));
-+
-+	for (i = 0; i < MAX_CHANNEL_NUM; i++) {
-+		snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)",
-+					"Laser tx bias current", i+1);
-+		PRINT_BIAS(power_string, sd.scd[i].bias_cur);
-+	}
-+
-+	for (i = 0; i < MAX_CHANNEL_NUM; i++) {
-+		snprintf(power_string, MAX_DESC_SIZE, "%s (Channel %d)",
-+					"Transmit avg optical power", i+1);
-+		PRINT_xX_PWR(power_string, sd.scd[i].tx_power);
-+	}
-+
-+	if (!sd.rx_power_type)
-+		rx_power_string = "Receiver signal OMA";
-+	else
-+		rx_power_string = "Rcvr signal avg optical power";
-+
-+	for (i = 0; i < MAX_CHANNEL_NUM; i++) {
-+		snprintf(power_string, MAX_DESC_SIZE, "%s(Channel %d)",
-+					rx_power_string, i+1);
-+		PRINT_xX_PWR(power_string, sd.scd[i].rx_power);
-+	}
-+
-+	if (sd.supports_alarms) {
-+		for (i = 0; sff8636_aw_flags[i].str; ++i) {
-+			printf("\t%-41s : %s\n", sff8636_aw_flags[i].str,
-+			       id[sff8636_aw_flags[i].offset]
-+			       & sff8636_aw_flags[i].value ? "On" : "Off");
-+		}
-+
-+		sff_show_thresholds(sd);
-+	}
-+
-+}
-+void sff8636_show_all(const __u8 *id, __u32 eeprom_len)
-+{
-+	sff8636_show_identifier(id);
-+	if ((id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP) ||
-+		(id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP_PLUS) ||
-+		(id[SFF8636_ID_OFFSET] == SFF8024_ID_QSFP28)) {
-+		sff8636_show_ext_identifier(id);
-+		sff8636_show_connector(id);
-+		sff8636_show_transceiver(id);
-+		sff8636_show_encoding(id);
-+		sff_show_value_with_unit(id, SFF8636_BR_NOMINAL_OFFSET,
-+				"BR, Nominal", 100, "Mbps");
-+		sff8636_show_rate_identifier(id);
-+		sff_show_value_with_unit(id, SFF8636_SM_LEN_OFFSET,
-+			     "Length (SMF,km)", 1, "km");
-+		sff_show_value_with_unit(id, SFF8636_OM3_LEN_OFFSET,
-+				"Length (OM3 50um)", 2, "m");
-+		sff_show_value_with_unit(id, SFF8636_OM2_LEN_OFFSET,
-+				"Length (OM2 50um)", 1, "m");
-+		sff_show_value_with_unit(id, SFF8636_OM1_LEN_OFFSET,
-+			     "Length (OM1 62.5um)", 1, "m");
-+		sff_show_value_with_unit(id, SFF8636_CBL_LEN_OFFSET,
-+			     "Length (Copper or Active cable)", 1, "m");
-+		sff8636_show_wavelength_or_copper_compliance(id);
-+		sff_show_ascii(id, SFF8636_VENDOR_NAME_START_OFFSET,
-+			       SFF8636_VENDOR_NAME_END_OFFSET, "Vendor name");
-+		sff8636_show_oui(id);
-+		sff_show_ascii(id, SFF8636_VENDOR_PN_START_OFFSET,
-+			       SFF8636_VENDOR_PN_END_OFFSET, "Vendor PN");
-+		sff_show_ascii(id, SFF8636_VENDOR_REV_START_OFFSET,
-+			       SFF8636_VENDOR_REV_END_OFFSET, "Vendor rev");
-+		sff_show_ascii(id, SFF8636_VENDOR_SN_START_OFFSET,
-+			       SFF8636_VENDOR_SN_END_OFFSET, "Vendor SN");
-+		sff8636_show_revision_compliance(id);
-+		sff8636_show_dom(id, eeprom_len);
-+	}
-+}
-diff --git a/qsfp.h b/qsfp.h
-new file mode 100644
-index 0000000..553ca5f
---- /dev/null
-+++ b/qsfp.h
-@@ -0,0 +1,595 @@
-+/*
-+ * SFF 8636 standards based QSFP EEPROM Field Definitions
-+ *
-+ * Vidya Ravipati <vidya@cumulusnetworks.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ */
-+
-+#ifndef QSFP_H__
-+#define QSFP_H__
-+
-+/*------------------------------------------------------------------------------
-+ *
-+ * QSFP EEPROM data structures
-+ *
-+ * register info from SFF-8636 Rev 2.7
-+ */
-+
-+/*------------------------------------------------------------------------------
-+ *
-+ * Lower Memory Page 00h
-+ * Measurement, Diagnostic and Control Functions
-+ *
-+ */
-+/* Identifier - 0 */
-+/* Values are defined under SFF8024_ID_OFFSET */
-+#define	SFF8636_ID_OFFSET	0x00
-+
-+#define	SFF8636_REV_COMPLIANCE_OFFSET	0x01
-+#define	 SFF8636_REV_UNSPECIFIED		0x00
-+#define	 SFF8636_REV_8436_48			0x01
-+#define	 SFF8636_REV_8436_8636			0x02
-+#define	 SFF8636_REV_8636_13			0x03
-+#define	 SFF8636_REV_8636_14			0x04
-+#define	 SFF8636_REV_8636_15			0x05
-+#define	 SFF8636_REV_8636_20			0x06
-+#define	 SFF8636_REV_8636_27			0x07
-+
-+#define	SFF8636_STATUS_2_OFFSET	0x02
-+/* Flat Memory:0- Paging, 1- Page 0 only */
-+#define	 SFF8636_STATUS_PAGE_3_PRESENT		(1 << 2)
-+#define	 SFF8636_STATUS_INTL_OUTPUT		(1 << 1)
-+#define	 SFF8636_STATUS_DATA_NOT_READY		(1 << 0)
-+
-+/* Channel Status Interrupt Flags - 3-5 */
-+#define	SFF8636_LOS_AW_OFFSET	0x03
-+#define	 SFF8636_TX4_LOS_AW		(1 << 7)
-+#define	 SFF8636_TX3_LOS_AW		(1 << 6)
-+#define	 SFF8636_TX2_LOS_AW		(1 << 5)
-+#define	 SFF8636_TX1_LOS_AW		(1 << 4)
-+#define	 SFF8636_RX4_LOS_AW		(1 << 3)
-+#define	 SFF8636_RX3_LOS_AW		(1 << 2)
-+#define	 SFF8636_RX2_LOS_AW		(1 << 1)
-+#define	 SFF8636_RX1_LOS_AW		(1 << 0)
-+
-+#define	SFF8636_FAULT_AW_OFFSET	0x04
-+#define	 SFF8636_TX4_FAULT_AW	(1 << 3)
-+#define	 SFF8636_TX3_FAULT_AW	(1 << 2)
-+#define	 SFF8636_TX2_FAULT_AW	(1 << 1)
-+#define	 SFF8636_TX1_FAULT_AW	(1 << 0)
-+
-+/* Module Monitor Interrupt Flags - 6-8 */
-+#define	SFF8636_TEMP_AW_OFFSET	0x06
-+#define	 SFF8636_TEMP_HALARM_STATUS		(1 << 7)
-+#define	 SFF8636_TEMP_LALARM_STATUS		(1 << 6)
-+#define	 SFF8636_TEMP_HWARN_STATUS		(1 << 5)
-+#define	 SFF8636_TEMP_LWARN_STATUS		(1 << 4)
-+
-+#define	SFF8636_VCC_AW_OFFSET	0x07
-+#define	 SFF8636_VCC_HALARM_STATUS		(1 << 7)
-+#define	 SFF8636_VCC_LALARM_STATUS		(1 << 6)
-+#define	 SFF8636_VCC_HWARN_STATUS		(1 << 5)
-+#define	 SFF8636_VCC_LWARN_STATUS		(1 << 4)
-+
-+/* Channel Monitor Interrupt Flags - 9-21 */
-+#define	SFF8636_RX_PWR_12_AW_OFFSET	0x09
-+#define	 SFF8636_RX_PWR_1_HALARM		(1 << 7)
-+#define	 SFF8636_RX_PWR_1_LALARM		(1 << 6)
-+#define	 SFF8636_RX_PWR_1_HWARN			(1 << 5)
-+#define	 SFF8636_RX_PWR_1_LWARN			(1 << 4)
-+#define	 SFF8636_RX_PWR_2_HALARM		(1 << 3)
-+#define	 SFF8636_RX_PWR_2_LALARM		(1 << 2)
-+#define	 SFF8636_RX_PWR_2_HWARN			(1 << 1)
-+#define	 SFF8636_RX_PWR_2_LWARN			(1 << 0)
-+
-+#define	SFF8636_RX_PWR_34_AW_OFFSET	0x0A
-+#define	 SFF8636_RX_PWR_3_HALARM		(1 << 7)
-+#define	 SFF8636_RX_PWR_3_LALARM		(1 << 6)
-+#define	 SFF8636_RX_PWR_3_HWARN			(1 << 5)
-+#define	 SFF8636_RX_PWR_3_LWARN			(1 << 4)
-+#define	 SFF8636_RX_PWR_4_HALARM		(1 << 3)
-+#define	 SFF8636_RX_PWR_4_LALARM		(1 << 2)
-+#define	 SFF8636_RX_PWR_4_HWARN			(1 << 1)
-+#define	 SFF8636_RX_PWR_4_LWARN			(1 << 0)
-+
-+#define	SFF8636_TX_BIAS_12_AW_OFFSET	0x0B
-+#define	 SFF8636_TX_BIAS_1_HALARM		(1 << 7)
-+#define	 SFF8636_TX_BIAS_1_LALARM		(1 << 6)
-+#define	 SFF8636_TX_BIAS_1_HWARN		(1 << 5)
-+#define	 SFF8636_TX_BIAS_1_LWARN		(1 << 4)
-+#define	 SFF8636_TX_BIAS_2_HALARM		(1 << 3)
-+#define	 SFF8636_TX_BIAS_2_LALARM		(1 << 2)
-+#define	 SFF8636_TX_BIAS_2_HWARN		(1 << 1)
-+#define	 SFF8636_TX_BIAS_2_LWARN		(1 << 0)
-+
-+#define	SFF8636_TX_BIAS_34_AW_OFFSET	0xC
-+#define	 SFF8636_TX_BIAS_3_HALARM		(1 << 7)
-+#define	 SFF8636_TX_BIAS_3_LALARM		(1 << 6)
-+#define	 SFF8636_TX_BIAS_3_HWARN		(1 << 5)
-+#define	 SFF8636_TX_BIAS_3_LWARN		(1 << 4)
-+#define	 SFF8636_TX_BIAS_4_HALARM		(1 << 3)
-+#define	 SFF8636_TX_BIAS_4_LALARM		(1 << 2)
-+#define	 SFF8636_TX_BIAS_4_HWARN		(1 << 1)
-+#define	 SFF8636_TX_BIAS_4_LWARN		(1 << 0)
-+
-+#define	SFF8636_TX_PWR_12_AW_OFFSET	0x0D
-+#define	 SFF8636_TX_PWR_1_HALARM		(1 << 7)
-+#define	 SFF8636_TX_PWR_1_LALARM		(1 << 6)
-+#define	 SFF8636_TX_PWR_1_HWARN			(1 << 5)
-+#define	 SFF8636_TX_PWR_1_LWARN			(1 << 4)
-+#define	 SFF8636_TX_PWR_2_HALARM		(1 << 3)
-+#define	 SFF8636_TX_PWR_2_LALARM		(1 << 2)
-+#define	 SFF8636_TX_PWR_2_HWARN			(1 << 1)
-+#define	 SFF8636_TX_PWR_2_LWARN			(1 << 0)
-+
-+#define	SFF8636_TX_PWR_34_AW_OFFSET	0x0E
-+#define	 SFF8636_TX_PWR_3_HALARM		(1 << 7)
-+#define	 SFF8636_TX_PWR_3_LALARM		(1 << 6)
-+#define	 SFF8636_TX_PWR_3_HWARN			(1 << 5)
-+#define	 SFF8636_TX_PWR_3_LWARN			(1 << 4)
-+#define	 SFF8636_TX_PWR_4_HALARM		(1 << 3)
-+#define	 SFF8636_TX_PWR_4_LALARM		(1 << 2)
-+#define	 SFF8636_TX_PWR_4_HWARN			(1 << 1)
-+#define	 SFF8636_TX_PWR_4_LWARN			(1 << 0)
-+
-+/* Module Monitoring Values - 22-33 */
-+#define	SFF8636_TEMP_CURR		0x16
-+#define	SFF8636_TEMP_MSB_OFFSET		0x16
-+#define	SFF8636_TEMP_LSB_OFFSET		0x17
-+
-+#define	SFF8636_VCC_CURR		0x1A
-+#define	SFF8636_VCC_MSB_OFFSET		0x1A
-+#define	SFF8636_VCC_LSB_OFFSET		0x1B
-+
-+/* Channel Monitoring Values - 34-81 */
-+#define	SFF8636_RX_PWR_1_OFFSET		0x22
-+#define	SFF8636_RX_PWR_2_OFFSET		0x24
-+#define	SFF8636_RX_PWR_3_OFFSET		0x26
-+#define	SFF8636_RX_PWR_4_OFFSET		0x28
-+
-+#define	SFF8636_TX_BIAS_1_OFFSET	0x2A
-+#define	SFF8636_TX_BIAS_2_OFFSET	0x2C
-+#define	SFF8636_TX_BIAS_3_OFFSET	0x2E
-+#define	SFF8636_TX_BIAS_4_OFFSET	0x30
-+
-+#define	SFF8636_TX_PWR_1_OFFSET		0x32
-+#define	SFF8636_TX_PWR_2_OFFSET		0x34
-+#define	SFF8636_TX_PWR_3_OFFSET		0x36
-+#define	SFF8636_TX_PWR_4_OFFSET		0x38
-+
-+/* Control Bytes - 86 - 99 */
-+#define	SFF8636_TX_DISABLE_OFFSET	0x56
-+#define	 SFF8636_TX_DISABLE_4			(1 << 3)
-+#define	 SFF8636_TX_DISABLE_3			(1 << 2)
-+#define	 SFF8636_TX_DISABLE_2			(1 << 1)
-+#define	 SFF8636_TX_DISABLE_1			(1 << 0)
-+
-+#define	SFF8636_RX_RATE_SELECT_OFFSET	0x57
-+#define	 SFF8636_RX_RATE_SELECT_4_MASK		(3 << 6)
-+#define	 SFF8636_RX_RATE_SELECT_3_MASK		(3 << 4)
-+#define	 SFF8636_RX_RATE_SELECT_2_MASK		(3 << 2)
-+#define	 SFF8636_RX_RATE_SELECT_1_MASK		(3 << 0)
-+
-+#define	SFF8636_TX_RATE_SELECT_OFFSET	0x58
-+#define	 SFF8636_TX_RATE_SELECT_4_MASK		(3 << 6)
-+#define	 SFF8636_TX_RATE_SELECT_3_MASK		(3 << 4)
-+#define	 SFF8636_TX_RATE_SELECT_2_MASK		(3 << 2)
-+#define	 SFF8636_TX_RATE_SELECT_1_MASK		(3 << 0)
-+
-+#define	SFF8636_RX_APP_SELECT_4_OFFSET	0x58
-+#define	SFF8636_RX_APP_SELECT_3_OFFSET	0x59
-+#define	SFF8636_RX_APP_SELECT_2_OFFSET	0x5A
-+#define	SFF8636_RX_APP_SELECT_1_OFFSET	0x5B
-+
-+#define	SFF8636_PWR_MODE_OFFSET		0x5D
-+#define	 SFF8636_HIGH_PWR_ENABLE		(1 << 2)
-+#define	 SFF8636_LOW_PWR_MODE			(1 << 1)
-+#define	 SFF8636_PWR_OVERRIDE			(1 << 0)
-+
-+#define	SFF8636_TX_APP_SELECT_4_OFFSET	0x5E
-+#define	SFF8636_TX_APP_SELECT_3_OFFSET	0x5F
-+#define	SFF8636_TX_APP_SELECT_2_OFFSET	0x60
-+#define	SFF8636_TX_APP_SELECT_1_OFFSET	0x61
-+
-+#define	SFF8636_LOS_MASK_OFFSET		0x64
-+#define	 SFF8636_TX_LOS_4_MASK			(1 << 7)
-+#define	 SFF8636_TX_LOS_3_MASK			(1 << 6)
-+#define	 SFF8636_TX_LOS_2_MASK			(1 << 5)
-+#define	 SFF8636_TX_LOS_1_MASK			(1 << 4)
-+#define	 SFF8636_RX_LOS_4_MASK			(1 << 3)
-+#define	 SFF8636_RX_LOS_3_MASK			(1 << 2)
-+#define	 SFF8636_RX_LOS_2_MASK			(1 << 1)
-+#define	 SFF8636_RX_LOS_1_MASK			(1 << 0)
-+
-+#define	SFF8636_FAULT_MASK_OFFSET	0x65
-+#define	 SFF8636_TX_FAULT_1_MASK		(1 << 3)
-+#define	 SFF8636_TX_FAULT_2_MASK		(1 << 2)
-+#define	 SFF8636_TX_FAULT_3_MASK		(1 << 1)
-+#define	 SFF8636_TX_FAULT_4_MASK		(1 << 0)
-+
-+#define	SFF8636_TEMP_MASK_OFFSET	0x67
-+#define	 SFF8636_TEMP_HALARM_MASK		(1 << 7)
-+#define	 SFF8636_TEMP_LALARM_MASK		(1 << 6)
-+#define	 SFF8636_TEMP_HWARN_MASK		(1 << 5)
-+#define	 SFF8636_TEMP_LWARN_MASK		(1 << 4)
-+
-+#define	SFF8636_VCC_MASK_OFFSET		0x68
-+#define	 SFF8636_VCC_HALARM_MASK		(1 << 7)
-+#define	 SFF8636_VCC_LALARM_MASK		(1 << 6)
-+#define	 SFF8636_VCC_HWARN_MASK			(1 << 5)
-+#define	 SFF8636_VCC_LWARN_MASK			(1 << 4)
-+
-+/*------------------------------------------------------------------------------
-+ *
-+ * Upper Memory Page 00h
-+ * Serial ID - Base ID, Extended ID and Vendor Specific ID fields
-+ *
-+ */
-+/* Identifier - 128 */
-+/* Identifier values same as Lower Memory Page 00h */
-+#define	SFF8636_UPPER_PAGE_0_ID_OFFSET		0x80
-+
-+/* Extended Identifier - 128 */
-+#define SFF8636_EXT_ID_OFFSET		0x81
-+#define	 SFF8636_EXT_ID_PWR_CLASS_MASK		0xC0
-+#define	  SFF8636_EXT_ID_PWR_CLASS_1		(0 << 6)
-+#define	  SFF8636_EXT_ID_PWR_CLASS_2		(1 << 6)
-+#define	  SFF8636_EXT_ID_PWR_CLASS_3		(2 << 6)
-+#define	  SFF8636_EXT_ID_PWR_CLASS_4		(3 << 6)
-+#define	 SFF8636_EXT_ID_CLIE_MASK		0x10
-+#define	  SFF8636_EXT_ID_CLIEI_CODE_PRESENT	(1 << 4)
-+#define	 SFF8636_EXT_ID_CDR_TX_MASK		0x08
-+#define	  SFF8636_EXT_ID_CDR_TX_PRESENT		(1 << 3)
-+#define	 SFF8636_EXT_ID_CDR_RX_MASK		0x04
-+#define	  SFF8636_EXT_ID_CDR_RX_PRESENT		(1 << 2)
-+#define	 SFF8636_EXT_ID_EPWR_CLASS_MASK		0x03
-+#define	  SFF8636_EXT_ID_PWR_CLASS_LEGACY	0
-+#define	  SFF8636_EXT_ID_PWR_CLASS_5		1
-+#define	  SFF8636_EXT_ID_PWR_CLASS_6		2
-+#define	  SFF8636_EXT_ID_PWR_CLASS_7		3
-+
-+/* Connector Values offset - 130 */
-+/* Values are defined under SFF8024_CTOR */
-+#define	SFF8636_CTOR_OFFSET		0x82
-+#define	 SFF8636_CTOR_UNKNOWN			0x00
-+#define	 SFF8636_CTOR_SC			0x01
-+#define	 SFF8636_CTOR_FC_STYLE_1		0x02
-+#define	 SFF8636_CTOR_FC_STYLE_2		0x03
-+#define	 SFF8636_CTOR_BNC_TNC			0x04
-+#define	 SFF8636_CTOR_FC_COAX			0x05
-+#define	 SFF8636_CTOR_FIBER_JACK		0x06
-+#define	 SFF8636_CTOR_LC			0x07
-+#define	 SFF8636_CTOR_MT_RJ			0x08
-+#define	 SFF8636_CTOR_MU			0x09
-+#define	 SFF8636_CTOR_SG			0x0A
-+#define	 SFF8636_CTOR_OPT_PT			0x0B
-+#define	 SFF8636_CTOR_MPO			0x0C
-+/* 0D-1Fh --- Reserved */
-+#define	 SFF8636_CTOR_HSDC_II			0x20
-+#define	 SFF8636_CTOR_COPPER_PT			0x21
-+#define	 SFF8636_CTOR_RJ45			0x22
-+#define	 SFF8636_CTOR_NO_SEPARABLE		0x23
-+#define	 SFF8636_CTOR_MXC_2X16			0x24
-+
-+/* Specification Compliance - 131-138 */
-+/* Ethernet Compliance Codes - 131 */
-+#define	SFF8636_ETHERNET_COMP_OFFSET	0x83
-+#define	 SFF8636_ETHERNET_RSRVD			(1 << 7)
-+#define	 SFF8636_ETHERNET_10G_LRM		(1 << 6)
-+#define	 SFF8636_ETHERNET_10G_LR		(1 << 5)
-+#define	 SFF8636_ETHERNET_10G_SR		(1 << 4)
-+#define	 SFF8636_ETHERNET_40G_CR4		(1 << 3)
-+#define	 SFF8636_ETHERNET_40G_SR4		(1 << 2)
-+#define	 SFF8636_ETHERNET_40G_LR4		(1 << 1)
-+#define	 SFF8636_ETHERNET_40G_ACTIVE	(1 << 0)
-+
-+/* SONET Compliance Codes - 132 */
-+#define	SFF8636_SONET_COMP_OFFSET	0x84
-+#define	 SFF8636_SONET_40G_OTN			(1 << 3)
-+#define	 SFF8636_SONET_OC48_LR			(1 << 2)
-+#define	 SFF8636_SONET_OC48_IR			(1 << 1)
-+#define	 SFF8636_SONET_OC48_SR			(1 << 0)
-+
-+/* SAS/SATA Complaince Codes - 133 */
-+#define	SFF8636_SAS_COMP_OFFSET		0x85
-+#define	 SFF8636_SAS_12G			(1 << 6)
-+#define	 SFF8636_SAS_6G				(1 << 5)
-+#define	 SFF8636_SAS_3G				(1 << 4)
-+
-+/* Gigabit Ethernet Compliance Codes - 134 */
-+#define	SFF8636_GIGE_COMP_OFFSET	0x86
-+#define	 SFF8636_GIGE_1000_BASE_T		(1 << 3)
-+#define	 SFF8636_GIGE_1000_BASE_CX		(1 << 2)
-+#define	 SFF8636_GIGE_1000_BASE_LX		(1 << 1)
-+#define	 SFF8636_GIGE_1000_BASE_SX		(1 << 0)
-+
-+/* Fibre Channel Link length/Transmitter Tech. - 135,136 */
-+#define	SFF8636_FC_LEN_OFFSET		0x87
-+#define	 SFF8636_FC_LEN_VERY_LONG		(1 << 7)
-+#define	 SFF8636_FC_LEN_SHORT			(1 << 6)
-+#define	 SFF8636_FC_LEN_INT			(1 << 5)
-+#define	 SFF8636_FC_LEN_LONG			(1 << 4)
-+#define	 SFF8636_FC_LEN_MED			(1 << 3)
-+#define	 SFF8636_FC_TECH_LONG_LC		(1 << 1)
-+#define	 SFF8636_FC_TECH_ELEC_INTER		(1 << 0)
-+
-+#define	SFF8636_FC_TECH_OFFSET		0x88
-+#define	 SFF8636_FC_TECH_ELEC_INTRA		(1 << 7)
-+#define	 SFF8636_FC_TECH_SHORT_WO_OFC		(1 << 6)
-+#define	 SFF8636_FC_TECH_SHORT_W_OFC		(1 << 5)
-+#define	 SFF8636_FC_TECH_LONG_LL		(1 << 4)
-+
-+/* Fibre Channel Transmitter Media - 137 */
-+#define	SFF8636_FC_TRANS_MEDIA_OFFSET	0x89
-+/* Twin Axial Pair */
-+#define	 SFF8636_FC_TRANS_MEDIA_TW		(1 << 7)
-+/* Shielded Twisted Pair */
-+#define	 SFF8636_FC_TRANS_MEDIA_TP		(1 << 6)
-+/* Miniature Coax */
-+#define	 SFF8636_FC_TRANS_MEDIA_MI		(1 << 5)
-+/* Video Coax */
-+#define	 SFF8636_FC_TRANS_MEDIA_TV		(1 << 4)
-+/* Multi-mode 62.5m */
-+#define	 SFF8636_FC_TRANS_MEDIA_M6		(1 << 3)
-+/* Multi-mode 50m */
-+#define	 SFF8636_FC_TRANS_MEDIA_M5		(1 << 2)
-+/* Multi-mode 50um */
-+#define	 SFF8636_FC_TRANS_MEDIA_OM3		(1 << 1)
-+/* Single Mode */
-+#define	 SFF8636_FC_TRANS_MEDIA_SM		(1 << 0)
-+
-+/* Fibre Channel Speed - 138 */
-+#define	SFF8636_FC_SPEED_OFFSET		0x8A
-+#define	 SFF8636_FC_SPEED_1200_MBPS		(1 << 7)
-+#define	 SFF8636_FC_SPEED_800_MBPS		(1 << 6)
-+#define	 SFF8636_FC_SPEED_1600_MBPS		(1 << 5)
-+#define	 SFF8636_FC_SPEED_400_MBPS		(1 << 4)
-+#define	 SFF8636_FC_SPEED_200_MBPS		(1 << 2)
-+#define	 SFF8636_FC_SPEED_100_MBPS		(1 << 0)
-+
-+/* Encoding - 139 */
-+/* Values are defined under SFF8024_ENCODING */
-+#define	SFF8636_ENCODING_OFFSET		0x8B
-+#define	 SFF8636_ENCODING_MANCHESTER	0x06
-+#define	 SFF8636_ENCODING_64B66B		0x05
-+#define	 SFF8636_ENCODING_SONET			0x04
-+#define	 SFF8636_ENCODING_NRZ			0x03
-+#define	 SFF8636_ENCODING_4B5B			0x02
-+#define	 SFF8636_ENCODING_8B10B			0x01
-+#define	 SFF8636_ENCODING_UNSPEC		0x00
-+
-+/* BR, Nominal - 140 */
-+#define	SFF8636_BR_NOMINAL_OFFSET	0x8C
-+
-+/* Extended RateSelect - 141 */
-+#define	SFF8636_EXT_RS_OFFSET		0x8D
-+#define	 SFF8636_EXT_RS_V1			(1 << 0)
-+
-+/* Length (Standard SM Fiber)-km - 142 */
-+#define	SFF8636_SM_LEN_OFFSET		0x8E
-+
-+/* Length (OM3)-Unit 2m - 143 */
-+#define	SFF8636_OM3_LEN_OFFSET		0x8F
-+
-+/* Length (OM2)-Unit 1m - 144 */
-+#define	SFF8636_OM2_LEN_OFFSET		0x90
-+
-+/* Length (OM1)-Unit 1m - 145 */
-+#define	SFF8636_OM1_LEN_OFFSET		0x91
-+
-+/* Cable Assembly Length -Unit 1m - 146 */
-+#define	SFF8636_CBL_LEN_OFFSET		0x92
-+
-+/* Device Technology - 147 */
-+#define	SFF8636_DEVICE_TECH_OFFSET	0x93
-+/* Transmitter Technology */
-+#define	 SFF8636_TRANS_TECH_MASK		0xF0
-+/* Copper cable, linear active equalizers */
-+#define	 SFF8636_TRANS_COPPER_LNR_EQUAL		(15 << 4)
-+/* Copper cable, near end limiting active equalizers */
-+#define	 SFF8636_TRANS_COPPER_NEAR_EQUAL	(14 << 4)
-+/* Copper cable, far end limiting active equalizers */
-+#define	 SFF8636_TRANS_COPPER_FAR_EQUAL		(13 << 4)
-+/* Copper cable, near & far end limiting active equalizers */
-+#define	 SFF8636_TRANS_COPPER_LNR_FAR_EQUAL	(12 << 4)
-+/* Copper cable, passive equalized */
-+#define	 SFF8636_TRANS_COPPER_PAS_EQUAL		(11 << 4)
-+/* Copper cable, unequalized */
-+#define	 SFF8636_TRANS_COPPER_PAS_UNEQUAL	(10 << 4)
-+/* 1490 nm DFB */
-+#define	 SFF8636_TRANS_1490_DFB			(9 << 4)
-+/* Others */
-+#define	 SFF8636_TRANS_OTHERS			(8 << 4)
-+/* 1550 nm EML */
-+#define	 SFF8636_TRANS_1550_EML			(7 << 4)
-+/* 1310 nm EML */
-+#define	 SFF8636_TRANS_1310_EML			(6 << 4)
-+/* 1550 nm DFB */
-+#define	 SFF8636_TRANS_1550_DFB			(5 << 4)
-+/* 1310 nm DFB */
-+#define	 SFF8636_TRANS_1310_DFB			(4 << 4)
-+/* 1310 nm FP */
-+#define	 SFF8636_TRANS_1310_FP			(3 << 4)
-+/* 1550 nm VCSEL */
-+#define	 SFF8636_TRANS_1550_VCSEL		(2 << 4)
-+/* 1310 nm VCSEL */
-+#define	 SFF8636_TRANS_1310_VCSEL		(1 << 4)
-+/* 850 nm VCSEL */
-+#define	 SFF8636_TRANS_850_VCSEL		(0 << 4)
-+
-+ /* Active/No wavelength control */
-+#define	 SFF8636_DEV_TECH_ACTIVE_WAVE_LEN	(1 << 3)
-+/* Cooled transmitter */
-+#define	 SFF8636_DEV_TECH_COOL_TRANS		(1 << 2)
-+/* APD/Pin Detector */
-+#define	 SFF8636_DEV_TECH_APD_DETECTOR		(1 << 1)
-+/* Transmitter tunable */
-+#define	 SFF8636_DEV_TECH_TUNABLE		(1 << 0)
-+
-+/* Vendor Name - 148-163 */
-+#define	 SFF8636_VENDOR_NAME_START_OFFSET	0x94
-+#define	 SFF8636_VENDOR_NAME_END_OFFSET		0xA3
-+
-+/* Extended Module Codes - 164 */
-+#define	 SFF8636_EXT_MOD_CODE_OFFSET	0xA4
-+#define	  SFF8636_EXT_MOD_INFINIBAND_EDR	(1 << 4)
-+#define	  SFF8636_EXT_MOD_INFINIBAND_FDR	(1 << 3)
-+#define	  SFF8636_EXT_MOD_INFINIBAND_QDR	(1 << 2)
-+#define	  SFF8636_EXT_MOD_INFINIBAND_DDR	(1 << 1)
-+#define	  SFF8636_EXT_MOD_INFINIBAND_SDR	(1 << 0)
-+
-+/* Vendor OUI - 165-167 */
-+#define	 SFF8636_VENDOR_OUI_OFFSET		0xA5
-+#define	  SFF8636_VENDOR_OUI_LEN		3
-+
-+/* Vendor OUI - 165-167 */
-+#define	 SFF8636_VENDOR_PN_START_OFFSET		0xA8
-+#define	 SFF8636_VENDOR_PN_END_OFFSET		0xB7
-+
-+/* Vendor Revision - 184-185 */
-+#define	 SFF8636_VENDOR_REV_START_OFFSET	0xB8
-+#define	 SFF8636_VENDOR_REV_END_OFFSET		0xB9
-+
-+/* Wavelength - 186-187 */
-+#define	 SFF8636_WAVELEN_HIGH_BYTE_OFFSET	0xBA
-+#define	 SFF8636_WAVELEN_LOW_BYTE_OFFSET	0xBB
-+
-+/* Wavelength  Tolerance- 188-189 */
-+#define	 SFF8636_WAVE_TOL_HIGH_BYTE_OFFSET	0xBC
-+#define	 SFF8636_WAVE_TOL_LOW_BYTE_OFFSET	0xBD
-+
-+/* Max case temp - Other than 70 C - 190 */
-+#define	 SFF8636_MAXCASE_TEMP_OFFSET	0xBE
-+
-+/* CC_BASE - 191 */
-+#define	 SFF8636_CC_BASE_OFFSET		0xBF
-+
-+/* Option Values - 192-195 */
-+#define	 SFF8636_OPTION_1_OFFSET	0xC0
-+#define	 SFF8636_ETHERNET_UNSPECIFIED		0x00
-+#define	 SFF8636_ETHERNET_100G_AOC		0x01
-+#define	 SFF8636_ETHERNET_100G_SR4		0x02
-+#define	 SFF8636_ETHERNET_100G_LR4		0x03
-+#define	 SFF8636_ETHERNET_100G_ER4		0x04
-+#define	 SFF8636_ETHERNET_100G_SR10		0x05
-+#define	 SFF8636_ETHERNET_100G_CWDM4_FEC	0x06
-+#define	 SFF8636_ETHERNET_100G_PSM4		0x07
-+#define	 SFF8636_ETHERNET_100G_ACC		0x08
-+#define	 SFF8636_ETHERNET_100G_CWDM4_NO_FEC	0x09
-+#define	 SFF8636_ETHERNET_100G_RSVD1		0x0A
-+#define	 SFF8636_ETHERNET_100G_CR4		0x0B
-+#define	 SFF8636_ETHERNET_25G_CR_CA_S		0x0C
-+#define	 SFF8636_ETHERNET_25G_CR_CA_N		0x0D
-+#define	 SFF8636_ETHERNET_40G_ER4		0x10
-+#define	 SFF8636_ETHERNET_4X10_SR		0x11
-+#define	 SFF8636_ETHERNET_40G_PSM4		0x12
-+#define	 SFF8636_ETHERNET_G959_P1I1_2D1		0x13
-+#define	 SFF8636_ETHERNET_G959_P1S1_2D2		0x14
-+#define	 SFF8636_ETHERNET_G959_P1L1_2D2		0x15
-+#define	 SFF8636_ETHERNET_10GT_SFI		0x16
-+#define	 SFF8636_ETHERNET_100G_CLR4		0x17
-+#define	 SFF8636_ETHERNET_100G_AOC2		0x18
-+#define	 SFF8636_ETHERNET_100G_ACC2		0x19
-+
-+#define	 SFF8636_OPTION_2_OFFSET	0xC1
-+/* Rx output amplitude */
-+#define	  SFF8636_O2_RX_OUTPUT_AMP	(1 << 0)
-+#define	 SFF8636_OPTION_3_OFFSET	0xC2
-+/* Rx Squelch Disable */
-+#define	  SFF8636_O3_RX_SQL_DSBL	(1 << 3)
-+/* Rx Output Disable capable */
-+#define	  SFF8636_O3_RX_OUTPUT_DSBL	(1 << 2)
-+/* Tx Squelch Disable */
-+#define	  SFF8636_O3_TX_SQL_DSBL	(1 << 1)
-+/* Tx Squelch Impl */
-+#define	  SFF8636_O3_TX_SQL_IMPL	(1 << 0)
-+#define	 SFF8636_OPTION_4_OFFSET	0xC3
-+/* Memory Page 02 present */
-+#define	  SFF8636_O4_PAGE_02_PRESENT	(1 << 7)
-+/* Memory Page 01 present */
-+#define	  SFF8636_O4_PAGE_01_PRESENT	(1 << 6)
-+/* Rate Select implemented */
-+#define	  SFF8636_O4_RATE_SELECT	(1 << 5)
-+/* Tx_DISABLE implemented */
-+#define	  SFF8636_O4_TX_DISABLE		(1 << 4)
-+/* Tx_FAULT implemented */
-+#define	  SFF8636_O4_TX_FAULT		(1 << 3)
-+/* Tx Squelch implemented */
-+#define	  SFF8636_O4_TX_SQUELCH		(1 << 2)
-+/* Tx Loss of Signal */
-+#define	  SFF8636_O4_TX_LOS		(1 << 1)
-+
-+/* Vendor SN - 196-211 */
-+#define	 SFF8636_VENDOR_SN_START_OFFSET	0xC4
-+#define	 SFF8636_VENDOR_SN_END_OFFSET	0xD3
-+
-+/* Vendor Date - 212-219 */
-+#define	 SFF8636_DATE_YEAR_OFFSET	0xD4
-+#define	  SFF8636_DATE_YEAR_LEN			2
-+#define	 SFF8636_DATE_MONTH_OFFSET	0xD6
-+#define	  SFF8636_DATE_MONTH_LEN		2
-+#define	 SFF8636_DATE_DAY_OFFSET	0xD8
-+#define	  SFF8636_DATE_DAY_LEN			2
-+
-+/* Diagnostic Monitoring Type - 220 */
-+#define	 SFF8636_DIAG_TYPE_OFFSET	0xDC
-+#define	  SFF8636_RX_PWR_TYPE_MASK	0x8
-+#define	   SFF8636_RX_PWR_TYPE_AVG_PWR	(1 << 3)
-+#define	   SFF8636_RX_PWR_TYPE_OMA	(0 << 3)
-+#define	  SFF8636_TX_PWR_TYPE_MASK	0x4
-+#define	   SFF8636_TX_PWR_TYPE_AVG_PWR	(1 << 2)
-+
-+/* Enhanced Options - 221 */
-+#define	 SFF8636_ENH_OPTIONS_OFFSET	0xDD
-+#define	  SFF8636_RATE_SELECT_EXT_SUPPORT	(1 << 3)
-+#define	  SFF8636_RATE_SELECT_APP_TABLE_SUPPORT	(1 << 2)
-+
-+/* Check code - 223 */
-+#define	 SFF8636_CC_EXT_OFFSET		0xDF
-+#define	  SFF8636_CC_EXT_LEN		1
-+
-+/*------------------------------------------------------------------------------
-+ *
-+ * Upper Memory Page 03h
-+ * Contains module thresholds, channel thresholds and masks,
-+ * and optional channel controls
-+ *
-+ * Offset - Page Num(3) * PageSize(0x80) + Page offset
-+ */
-+
-+/* Module Thresholds (48 Bytes) 128-175 */
-+/* MSB at low address, LSB at high address */
-+#define	SFF8636_TEMP_HALRM		0x200
-+#define	SFF8636_TEMP_LALRM		0x202
-+#define	SFF8636_TEMP_HWARN		0x204
-+#define	SFF8636_TEMP_LWARN		0x206
-+
-+#define	SFF8636_VCC_HALRM		0x210
-+#define	SFF8636_VCC_LALRM		0x212
-+#define	SFF8636_VCC_HWARN		0x214
-+#define	SFF8636_VCC_LWARN		0x216
-+
-+#define	SFF8636_RX_PWR_HALRM		0x230
-+#define	SFF8636_RX_PWR_LALRM		0x232
-+#define	SFF8636_RX_PWR_HWARN		0x234
-+#define	SFF8636_RX_PWR_LWARN		0x236
-+
-+#define	SFF8636_TX_BIAS_HALRM		0x238
-+#define	SFF8636_TX_BIAS_LALRM		0x23A
-+#define	SFF8636_TX_BIAS_HWARN		0x23C
-+#define	SFF8636_TX_BIAS_LWARN		0x23E
-+
-+#define	SFF8636_TX_PWR_HALRM		0x240
-+#define	SFF8636_TX_PWR_LALRM		0x242
-+#define	SFF8636_TX_PWR_HWARN		0x244
-+#define	SFF8636_TX_PWR_LWARN		0x246
-+
-+#define	ETH_MODULE_SFF_8636_MAX_LEN	640
-+#define	ETH_MODULE_SFF_8436_MAX_LEN	640
-+
-+#endif /* QSFP_H__ */
--- 
-1.8.3.1
-
diff --git a/SOURCES/0006-ethtool-Enhancing-link-mode-bits-to-support-25G-50G-.patch b/SOURCES/0006-ethtool-Enhancing-link-mode-bits-to-support-25G-50G-.patch
deleted file mode 100644
index 9bd389a..0000000
--- a/SOURCES/0006-ethtool-Enhancing-link-mode-bits-to-support-25G-50G-.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From d1387987c21dbd4a41c1c5c3b6780b16545b19fc Mon Sep 17 00:00:00 2001
-From: Vidya Sagar Ravipati <vidya@cumulusnetworks.com>
-Date: Tue, 23 Aug 2016 06:30:33 -0700
-Subject: [PATCH 6/7] ethtool: Enhancing link mode bits to support 25G/50G/100G
-
-Enhancing link mode bits to support 25G/50G/100G
-for supported and advertised speed mode bits
-
-Signed-off-by: Vidya Sagar Ravipati <vidya@cumulusnetworks.com>
-Acked-By: David Decotigny <decot@googlers.com>
-Acked-By: David Decotigny <decot@googlers.com>
-Signed-off-by: John W. Linville <linville@tuxdriver.com>
-(cherry picked from commit ac2f96d5f281a67ab8796badfa40f2da14033aba)
----
- ethtool.c | 30 ++++++++++++++++++++++++++++++
- 1 file changed, 30 insertions(+)
-
-diff --git a/ethtool.c b/ethtool.c
-index ffb3573..3687ab0 100644
---- a/ethtool.c
-+++ b/ethtool.c
-@@ -504,6 +504,16 @@ static void init_global_link_mode_masks(void)
- 		ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT,
- 		ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT,
- 		ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
-+		ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
-+		ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
-+		ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
-+		ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
-+		ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
-+		ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
-+		ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
-+		ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
-+		ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
-+		ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
- 	};
- 	static const enum ethtool_link_mode_bit_indices
- 		additional_advertised_flags_bits[] = {
-@@ -624,6 +634,26 @@ static void dump_link_caps(const char *prefix, const char *an_prefix,
- 		  "56000baseSR4/Full" },
- 		{ 0, ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
- 		  "56000baseLR4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
-+		  "25000baseCR/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
-+		  "25000baseKR/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
-+		  "25000baseSR/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
-+		  "50000baseCR2/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
-+		  "50000baseKR2/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
-+		  "100000baseKR4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
-+		  "100000baseSR4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
-+		  "100000baseCR4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
-+		  "100000baseLR4_ER4/Full" },
-+		{ 0, ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
-+		  "50000baseSR2/Full" },
- 	};
- 	int indent;
- 	int did1, new_line_pend, i;
--- 
-1.8.3.1
-
diff --git a/SOURCES/0007-ethtool-Document-new-ethtool-advertise-speeds.patch b/SOURCES/0007-ethtool-Document-new-ethtool-advertise-speeds.patch
deleted file mode 100644
index b98e4f3..0000000
--- a/SOURCES/0007-ethtool-Document-new-ethtool-advertise-speeds.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 17e87eace95b8742252707d6719124af6e0f60c0 Mon Sep 17 00:00:00 2001
-From: Yuval Mintz <Yuval.Mintz@qlogic.com>
-Date: Mon, 22 Aug 2016 08:50:39 +0300
-Subject: [PATCH 7/7] ethtool: Document new ethtool advertise speeds
-
-Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
-Signed-off-by: John W. Linville <linville@tuxdriver.com>
-(cherry picked from commit 215d157b130c0a4af9bd4122fb69bc9908a22bca)
----
- ethtool.8.in | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/ethtool.8.in b/ethtool.8.in
-index 009711d..6eec78d 100644
---- a/ethtool.8.in
-+++ b/ethtool.8.in
-@@ -580,10 +580,20 @@ lB	l	lB.
- 0x80000	10000baseKR Full
- 0x200000	20000baseMLD2 Full	(not supported by IEEE standards)
- 0x400000	20000baseKR2 Full	(not supported by IEEE standards)
-+0x80000000	25000baseCR Full
-+0x100000000	25000baseKR Full
-+0x200000000	25000baseSR Full
- 0x800000	40000baseKR4 Full
- 0x1000000	40000baseCR4 Full
- 0x2000000	40000baseSR4 Full
- 0x4000000	40000baseLR4 Full
-+0x400000000	50000baseCR2 Full
-+0x800000000	50000baseKR2 Full
-+0x10000000000	50000baseSR2 Full
-+0x1000000000	100000baseKR4 Full
-+0x2000000000	100000baseSR4 Full
-+0x4000000000	100000baseCR4 Full
-+0x8000000000	100000baseLR4_ER4 Full
- .TE
- .TP
- .BI phyad \ N
--- 
-1.8.3.1
-
diff --git a/SPECS/ethtool.spec b/SPECS/ethtool.spec
index 31d5a78..3373cfd 100644
--- a/SPECS/ethtool.spec
+++ b/SPECS/ethtool.spec
@@ -1,7 +1,7 @@
 Name:		ethtool
 Epoch:		2
-Version:	4.5
-Release:	3%{?dist}
+Version:	4.8
+Release:	1%{?dist}
 Summary:	Settings tool for Ethernet NICs
 
 License:	GPLv2
@@ -21,13 +21,9 @@ URL:		http://ftp.kernel.org/pub/software/network/%{name}/
 Source0:	http://ftp.kernel.org/pub/software/network/%{name}/%{name}-%{version}.tar.xz
 BuildRequires:	automake, autoconf
 Conflicts:      filesystem < 3
-Patch0:		0001-ethtool.c-fix-memory-leaks.patch
-Patch1:		0002-ethtool.c-add-support-for-ETHTOOL_xLINKSETTINGS-ioctl.patch
-Patch2:		0003-ethtool-copy.h-sync-with-net.patch
-Patch3:		0004-ethtool-Reorganizing-SFF-8024-fields-for-SFP-QSFP.patch
-Patch4:		0005-ethtool-QSFP-Plus-QSFP28-Diagnostics-Information-Sup.patch
-Patch5:		0006-ethtool-Enhancing-link-mode-bits-to-support-25G-50G-.patch
-Patch6:		0007-ethtool-Document-new-ethtool-advertise-speeds.patch
+Patch0:		0001-ethtool-add-register-dump-support-for-fjes-driver.patch
+Patch1:		0002-ethtool-sync-help-output-for-x-X-with-man-page.patch
+Patch2:		0003-ethtool-Fix-the-advertise-parameter-logic.patch
 
 %description
 This utility allows querying and changing settings such as speed,
@@ -39,10 +35,6 @@ network devices, especially of Ethernet devices.
 %patch0 -p1
 %patch1 -p1
 %patch2 -p1
-%patch3 -p1
-%patch4 -p1
-%patch5 -p1
-%patch6 -p1
 
 # Only needed when using upstream git
 # aclocal
@@ -65,6 +57,18 @@ make DESTDIR=%{buildroot} INSTALL='install -p' install
 %{_mandir}/man8/%{name}.8*
 
 %changelog
+* Wed Mar 22 2017 Ivan Vecera <ivecera@redhat.com> - 2:4.8-1
+- Rebased against upstream v4.8
+
+* Fri Mar 17 2017 Ivan Vecera <ivecera@redhat.com> - 2:4.5-6
+- Fixed the "advertise" parameter logic
+
+* Tue Feb 21 2017 Ivan Vecera <ivecera@redhat.com> - 2:4.5-5
+- Fixed help page for commands -x and -X
+
+* Thu Feb  2 2017 Ivan Vecera <ivecera@redhat.com> - 2:4.5-4
+- Add register dump support for fjes driver
+
 * Tue Aug 16 2016 Ivan Vecera <ivecera@redhat.com> - 2:4.5-3
 - Added support for new ETHTOOL_xLINKSETTINGS API
 - Added support for diagnostics information for QSFP Plus/QSFP28 modules