diff --git a/.ethtool.metadata b/.ethtool.metadata
index 1c6dec2..8d4c891 100644
--- a/.ethtool.metadata
+++ b/.ethtool.metadata
@@ -1 +1 @@
-653112e78fea5230d4b4ea67f433c62b16bed071 SOURCES/ethtool-3.8.tar.xz
+cb01cb38c18474e21c3741aec9b58030b26ba489 SOURCES/ethtool-3.15.tar.xz
diff --git a/.gitignore b/.gitignore
index a9c3b11..dfb92ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/ethtool-3.8.tar.xz
+SOURCES/ethtool-3.15.tar.xz
diff --git a/SOURCES/0001-Add-string-to-display-support-for-KR-PHY.patch b/SOURCES/0001-Add-string-to-display-support-for-KR-PHY.patch
deleted file mode 100644
index 167a2de..0000000
--- a/SOURCES/0001-Add-string-to-display-support-for-KR-PHY.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 4b467d78c334f2bc72ea5ae66141546d218a9766 Mon Sep 17 00:00:00 2001
-From: "Vasundhara, Volam" <Vasundhara.Volam@Emulex.Com>
-Date: Tue, 12 Feb 2013 09:46:20 +0000
-Subject: [PATCH 1/2] ethtool: Add string to display support for KR PHY
-
-Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>
-Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
----
- ethtool.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/ethtool.c b/ethtool.c
-index acac32a..8cc10b5 100644
---- a/ethtool.c
-+++ b/ethtool.c
-@@ -512,6 +512,7 @@ dump_link_caps(const char *prefix, const char *an_prefix, u32 mask,
- 		{ 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" },
--- 
-1.8.3.1
-
diff --git a/SOURCES/0001-ethtool-copy.h-sync-with-net.patch b/SOURCES/0001-ethtool-copy.h-sync-with-net.patch
new file mode 100644
index 0000000..8b015cb
--- /dev/null
+++ b/SOURCES/0001-ethtool-copy.h-sync-with-net.patch
@@ -0,0 +1,680 @@
+From e63362618ed0b54fe8341c700cf5fe695a24b258 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sun, 21 Sep 2014 21:40:46 +0100
+Subject: [PATCH 1/4] ethtool-copy.h: sync with net
+
+This covers kernel changes up to:
+
+commit 38c891a49dec43dbb1575cc40d10dbd49c4961ab
+Author: Ben Hutchings <ben@decadent.org.uk>
+Date:   Thu May 15 01:07:16 2014 +0100
+
+    ethtool: Improve explanation of the two arrays following struct ethtool_rxfh
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ ethtool-copy.h | 478 +++++++++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 363 insertions(+), 115 deletions(-)
+
+diff --git a/ethtool-copy.h b/ethtool-copy.h
+index b5515c2..61b78fc 100644
+--- a/ethtool-copy.h
++++ b/ethtool-copy.h
+@@ -16,37 +16,97 @@
+ #include <linux/types.h>
+ #include <linux/if_ether.h>
+ 
+-/* This should work for both 32 and 64 bit userland. */
++/* All structures exposed to userland should be defined such that they
++ * have the same layout for 32-bit and 64-bit userland.
++ */
++
++/**
++ * struct ethtool_cmd - link control and status
++ * @cmd: Command number = %ETHTOOL_GSET or %ETHTOOL_SSET
++ * @supported: Bitmask of %SUPPORTED_* flags for the link modes,
++ *	physical connectors and other link features for which the
++ *	interface supports autonegotiation or auto-detection.
++ *	Read-only.
++ * @advertising: Bitmask of %ADVERTISED_* flags for the link modes,
++ *	physical connectors and other link features that are
++ *	advertised through autonegotiation or enabled for
++ *	auto-detection.
++ * @speed: Low bits of the speed
++ * @duplex: Duplex mode; one of %DUPLEX_*
++ * @port: Physical connector type; one of %PORT_*
++ * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not
++ *	applicable.  For clause 45 PHYs this is the PRTAD.
++ * @transceiver: Historically used to distinguish different possible
++ *	PHY types, but not in a consistent way.  Deprecated.
++ * @autoneg: Enable/disable autonegotiation and auto-detection;
++ *	either %AUTONEG_DISABLE or %AUTONEG_ENABLE
++ * @mdio_support: Bitmask of %ETH_MDIO_SUPPORTS_* flags for the MDIO
++ *	protocols supported by the interface; 0 if unknown.
++ *	Read-only.
++ * @maxtxpkt: Historically used to report TX IRQ coalescing; now
++ *	obsoleted by &struct ethtool_coalesce.  Read-only; deprecated.
++ * @maxrxpkt: Historically used to report RX IRQ coalescing; now
++ *	obsoleted by &struct ethtool_coalesce.  Read-only; deprecated.
++ * @speed_hi: High bits of the speed
++ * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of
++ *	%ETH_TP_MDI_*.  If the status is unknown or not applicable, the
++ *	value will be %ETH_TP_MDI_INVALID.  Read-only.
++ * @eth_tp_mdix_ctrl: Ethernet twisted pair MDI(-X) control; one of
++ *	%ETH_TP_MDI_*.  If MDI(-X) control is not implemented, reads
++ *	yield %ETH_TP_MDI_INVALID and writes may be ignored or rejected.
++ *	When written successfully, the link should be renegotiated if
++ *	necessary.
++ * @lp_advertising: Bitmask of %ADVERTISED_* flags for the link modes
++ *	and other link features that the link partner advertised
++ *	through autonegotiation; 0 if unknown or not applicable.
++ *	Read-only.
++ *
++ * The link speed in Mbps is split between @speed and @speed_hi.  Use
++ * the ethtool_cmd_speed() and ethtool_cmd_speed_set() functions to
++ * access it.
++ *
++ * If autonegotiation is disabled, the speed and @duplex represent the
++ * fixed link mode and are writable if the driver supports multiple
++ * link modes.  If it is enabled then they are read-only; if the link
++ * is up they represent the negotiated link mode; if the link is down,
++ * the speed is 0, %SPEED_UNKNOWN or the highest enabled speed and
++ * @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode.
++ *
++ * Some hardware interfaces may have multiple PHYs and/or physical
++ * connectors fitted or do not allow the driver to detect which are
++ * fitted.  For these interfaces @port and/or @phy_address may be
++ * writable, possibly dependent on @autoneg being %AUTONEG_DISABLE.
++ * Otherwise, attempts to write different values may be ignored or
++ * rejected.
++ *
++ * Users should assume that all fields not marked read-only are
++ * writable and subject to validation by the driver.  They should use
++ * %ETHTOOL_GSET to get the current values before making specific
++ * changes and then applying them with %ETHTOOL_SSET.
++ *
++ * Drivers that implement set_settings() should validate all fields
++ * other than @cmd that are not described as read-only or deprecated,
++ * and must ignore all fields described as read-only.
++ *
++ * Deprecated fields should be ignored by both users and drivers.
++ */
+ struct ethtool_cmd {
+ 	__u32	cmd;
+-	__u32	supported;	/* Features this interface supports */
+-	__u32	advertising;	/* Features this interface advertises */
+-	__u16	speed;	        /* The forced speed (lower bits) in
+-				 * Mbps. Please use
+-				 * ethtool_cmd_speed()/_set() to
+-				 * access it */
+-	__u8	duplex;		/* Duplex, half or full */
+-	__u8	port;		/* Which connector port */
+-	__u8	phy_address;	/* MDIO PHY address (PRTAD for clause 45).
+-				 * May be read-only or read-write
+-				 * depending on the driver.
+-				 */
+-	__u8	transceiver;	/* Which transceiver to use */
+-	__u8	autoneg;	/* Enable or disable autonegotiation */
+-	__u8	mdio_support;	/* MDIO protocols supported.  Read-only.
+-				 * Not set by all drivers.
+-				 */
+-	__u32	maxtxpkt;	/* Tx pkts before generating tx int */
+-	__u32	maxrxpkt;	/* Rx pkts before generating rx int */
+-	__u16	speed_hi;       /* The forced speed (upper
+-				 * bits) in Mbps. Please use
+-				 * ethtool_cmd_speed()/_set() to
+-				 * access it */
+-	__u8	eth_tp_mdix;	/* twisted pair MDI-X status */
+-	__u8    eth_tp_mdix_ctrl; /* twisted pair MDI-X control, when set,
+-				   * link should be renegotiated if necessary
+-				   */
+-	__u32	lp_advertising;	/* Features the link partner advertises */
++	__u32	supported;
++	__u32	advertising;
++	__u16	speed;
++	__u8	duplex;
++	__u8	port;
++	__u8	phy_address;
++	__u8	transceiver;
++	__u8	autoneg;
++	__u8	mdio_support;
++	__u32	maxtxpkt;
++	__u32	maxrxpkt;
++	__u16	speed_hi;
++	__u8	eth_tp_mdix;
++	__u8	eth_tp_mdix_ctrl;
++	__u32	lp_advertising;
+ 	__u32	reserved[2];
+ };
+ 
+@@ -79,37 +139,68 @@ static __inline__ __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep)
+ 
+ #define ETHTOOL_FWVERS_LEN	32
+ #define ETHTOOL_BUSINFO_LEN	32
+-/* these strings are set to whatever the driver author decides... */
++
++/**
++ * struct ethtool_drvinfo - general driver and device information
++ * @cmd: Command number = %ETHTOOL_GDRVINFO
++ * @driver: Driver short name.  This should normally match the name
++ *	in its bus driver structure (e.g. pci_driver::name).  Must
++ *	not be an empty string.
++ * @version: Driver version string; may be an empty string
++ * @fw_version: Firmware version string; may be an empty string
++ * @bus_info: Device bus address.  This should match the dev_name()
++ *	string for the underlying bus device, if there is one.  May be
++ *	an empty string.
++ * @n_priv_flags: Number of flags valid for %ETHTOOL_GPFLAGS and
++ *	%ETHTOOL_SPFLAGS commands; also the number of strings in the
++ *	%ETH_SS_PRIV_FLAGS set
++ * @n_stats: Number of u64 statistics returned by the %ETHTOOL_GSTATS
++ *	command; also the number of strings in the %ETH_SS_STATS set
++ * @testinfo_len: Number of results returned by the %ETHTOOL_TEST
++ *	command; also the number of strings in the %ETH_SS_TEST set
++ * @eedump_len: Size of EEPROM accessible through the %ETHTOOL_GEEPROM
++ *	and %ETHTOOL_SEEPROM commands, in bytes
++ * @regdump_len: Size of register dump returned by the %ETHTOOL_GREGS
++ *	command, in bytes
++ *
++ * Users can use the %ETHTOOL_GSSET_INFO command to get the number of
++ * strings in any string set (from Linux 2.6.34).
++ *
++ * Drivers should set at most @driver, @version, @fw_version and
++ * @bus_info in their get_drvinfo() implementation.  The ethtool
++ * core fills in the other fields using other driver operations.
++ */
+ struct ethtool_drvinfo {
+ 	__u32	cmd;
+-	char	driver[32];	/* driver short name, "tulip", "eepro100" */
+-	char	version[32];	/* driver version string */
+-	char	fw_version[ETHTOOL_FWVERS_LEN];	/* firmware version string */
+-	char	bus_info[ETHTOOL_BUSINFO_LEN];	/* Bus info for this IF. */
+-				/* For PCI devices, use pci_name(pci_dev). */
++	char	driver[32];
++	char	version[32];
++	char	fw_version[ETHTOOL_FWVERS_LEN];
++	char	bus_info[ETHTOOL_BUSINFO_LEN];
+ 	char	reserved1[32];
+ 	char	reserved2[12];
+-				/*
+-				 * Some struct members below are filled in
+-				 * using ops->get_sset_count().  Obtaining
+-				 * this info from ethtool_drvinfo is now
+-				 * deprecated; Use ETHTOOL_GSSET_INFO
+-				 * instead.
+-				 */
+-	__u32	n_priv_flags;	/* number of flags valid in ETHTOOL_GPFLAGS */
+-	__u32	n_stats;	/* number of u64's from ETHTOOL_GSTATS */
++	__u32	n_priv_flags;
++	__u32	n_stats;
+ 	__u32	testinfo_len;
+-	__u32	eedump_len;	/* Size of data from ETHTOOL_GEEPROM (bytes) */
+-	__u32	regdump_len;	/* Size of data from ETHTOOL_GREGS (bytes) */
++	__u32	eedump_len;
++	__u32	regdump_len;
+ };
+ 
+ #define SOPASS_MAX	6
+-/* wake-on-lan settings */
++
++/**
++ * struct ethtool_wolinfo - Wake-On-Lan configuration
++ * @cmd: Command number = %ETHTOOL_GWOL or %ETHTOOL_SWOL
++ * @supported: Bitmask of %WAKE_* flags for supported Wake-On-Lan modes.
++ *	Read-only.
++ * @wolopts: Bitmask of %WAKE_* flags for enabled Wake-On-Lan modes.
++ * @sopass: SecureOn(tm) password; meaningful only if %WAKE_MAGICSECURE
++ *	is set in @wolopts.
++ */
+ struct ethtool_wolinfo {
+ 	__u32	cmd;
+ 	__u32	supported;
+ 	__u32	wolopts;
+-	__u8	sopass[SOPASS_MAX]; /* SecureOn(tm) password */
++	__u8	sopass[SOPASS_MAX];
+ };
+ 
+ /* for passing single values */
+@@ -118,20 +209,51 @@ struct ethtool_value {
+ 	__u32	data;
+ };
+ 
+-/* for passing big chunks of data */
++/**
++ * struct ethtool_regs - hardware register dump
++ * @cmd: Command number = %ETHTOOL_GREGS
++ * @version: Dump format version.  This is driver-specific and may
++ *	distinguish different chips/revisions.  Drivers must use new
++ *	version numbers whenever the dump format changes in an
++ *	incompatible way.
++ * @len: On entry, the real length of @data.  On return, the number of
++ *	bytes used.
++ * @data: Buffer for the register dump
++ *
++ * Users should use %ETHTOOL_GDRVINFO to find the maximum length of
++ * a register dump for the interface.  They must allocate the buffer
++ * immediately following this structure.
++ */
+ struct ethtool_regs {
+ 	__u32	cmd;
+-	__u32	version; /* driver-specific, indicates different chips/revs */
+-	__u32	len; /* bytes */
++	__u32	version;
++	__u32	len;
+ 	__u8	data[0];
+ };
+ 
+-/* for passing EEPROM chunks */
++/**
++ * struct ethtool_eeprom - EEPROM dump
++ * @cmd: Command number = %ETHTOOL_GEEPROM, %ETHTOOL_GMODULEEEPROM or
++ *	%ETHTOOL_SEEPROM
++ * @magic: A 'magic cookie' value to guard against accidental changes.
++ *	The value passed in to %ETHTOOL_SEEPROM must match the value
++ *	returned by %ETHTOOL_GEEPROM for the same device.  This is
++ *	unused when @cmd is %ETHTOOL_GMODULEEEPROM.
++ * @offset: Offset within the EEPROM to begin reading/writing, in bytes
++ * @len: On entry, number of bytes to read/write.  On successful
++ *	return, number of bytes actually read/written.  In case of
++ *	error, this may indicate at what point the error occurred.
++ * @data: Buffer to read/write from
++ *
++ * Users may use %ETHTOOL_GDRVINFO or %ETHTOOL_GMODULEINFO to find
++ * the length of an on-board or module EEPROM, respectively.  They
++ * must allocate the buffer immediately following this structure.
++ */
+ struct ethtool_eeprom {
+ 	__u32	cmd;
+ 	__u32	magic;
+-	__u32	offset; /* in bytes */
+-	__u32	len; /* in bytes */
++	__u32	offset;
++	__u32	len;
+ 	__u8	data[0];
+ };
+ 
+@@ -229,17 +351,18 @@ struct ethtool_modinfo {
+  * @rate_sample_interval: How often to do adaptive coalescing packet rate
+  *	sampling, measured in seconds.  Must not be zero.
+  *
+- * Each pair of (usecs, max_frames) fields specifies this exit
+- * condition for interrupt coalescing:
++ * Each pair of (usecs, max_frames) fields specifies that interrupts
++ * should be coalesced until
+  *	(usecs > 0 && time_since_first_completion >= usecs) ||
+  *	(max_frames > 0 && completed_frames >= max_frames)
++ *
+  * It is illegal to set both usecs and max_frames to zero as this
+  * would cause interrupts to never be generated.  To disable
+  * coalescing, set usecs = 0 and max_frames = 1.
+  *
+  * Some implementations ignore the value of max_frames and use the
+- * condition:
+- *	time_since_first_completion >= usecs
++ * condition time_since_first_completion >= usecs
++ *
+  * This is deprecated.  Drivers for hardware that does not support
+  * counting completions should validate that max_frames == !rx_usecs.
+  *
+@@ -279,22 +402,37 @@ struct ethtool_coalesce {
+ 	__u32	rate_sample_interval;
+ };
+ 
+-/* for configuring RX/TX ring parameters */
++/**
++ * struct ethtool_ringparam - RX/TX ring parameters
++ * @cmd: Command number = %ETHTOOL_GRINGPARAM or %ETHTOOL_SRINGPARAM
++ * @rx_max_pending: Maximum supported number of pending entries per
++ *	RX ring.  Read-only.
++ * @rx_mini_max_pending: Maximum supported number of pending entries
++ *	per RX mini ring.  Read-only.
++ * @rx_jumbo_max_pending: Maximum supported number of pending entries
++ *	per RX jumbo ring.  Read-only.
++ * @tx_max_pending: Maximum supported number of pending entries per
++ *	TX ring.  Read-only.
++ * @rx_pending: Current maximum number of pending entries per RX ring
++ * @rx_mini_pending: Current maximum number of pending entries per RX
++ *	mini ring
++ * @rx_jumbo_pending: Current maximum number of pending entries per RX
++ *	jumbo ring
++ * @tx_pending: Current maximum supported number of pending entries
++ *	per TX ring
++ *
++ * If the interface does not have separate RX mini and/or jumbo rings,
++ * @rx_mini_max_pending and/or @rx_jumbo_max_pending will be 0.
++ *
++ * There may also be driver-dependent minimum values for the number
++ * of entries per ring.
++ */
+ struct ethtool_ringparam {
+-	__u32	cmd;	/* ETHTOOL_{G,S}RINGPARAM */
+-
+-	/* Read only attributes.  These indicate the maximum number
+-	 * of pending RX/TX ring entries the driver will allow the
+-	 * user to set.
+-	 */
++	__u32	cmd;
+ 	__u32	rx_max_pending;
+ 	__u32	rx_mini_max_pending;
+ 	__u32	rx_jumbo_max_pending;
+ 	__u32	tx_max_pending;
+-
+-	/* Values changeable by the user.  The valid values are
+-	 * in the range 1 to the "*_max_pending" counterpart above.
+-	 */
+ 	__u32	rx_pending;
+ 	__u32	rx_mini_pending;
+ 	__u32	rx_jumbo_pending;
+@@ -329,51 +467,96 @@ struct ethtool_channels {
+ 	__u32	combined_count;
+ };
+ 
+-/* for configuring link flow control parameters */
++/**
++ * struct ethtool_pauseparam - Ethernet pause (flow control) parameters
++ * @cmd: Command number = %ETHTOOL_GPAUSEPARAM or %ETHTOOL_SPAUSEPARAM
++ * @autoneg: Flag to enable autonegotiation of pause frame use
++ * @rx_pause: Flag to enable reception of pause frames
++ * @tx_pause: Flag to enable transmission of pause frames
++ *
++ * Drivers should reject a non-zero setting of @autoneg when
++ * autoneogotiation is disabled (or not supported) for the link.
++ *
++ * If the link is autonegotiated, drivers should use
++ * mii_advertise_flowctrl() or similar code to set the advertised
++ * pause frame capabilities based on the @rx_pause and @tx_pause flags,
++ * even if @autoneg is zero.  They should also allow the advertised
++ * pause frame capabilities to be controlled directly through the
++ * advertising field of &struct ethtool_cmd.
++ *
++ * If @autoneg is non-zero, the MAC is configured to send and/or
++ * receive pause frames according to the result of autonegotiation.
++ * Otherwise, it is configured directly based on the @rx_pause and
++ * @tx_pause flags.
++ */
+ struct ethtool_pauseparam {
+-	__u32	cmd;	/* ETHTOOL_{G,S}PAUSEPARAM */
+-
+-	/* If the link is being auto-negotiated (via ethtool_cmd.autoneg
+-	 * being true) the user may set 'autoneg' here non-zero to have the
+-	 * pause parameters be auto-negotiated too.  In such a case, the
+-	 * {rx,tx}_pause values below determine what capabilities are
+-	 * advertised.
+-	 *
+-	 * If 'autoneg' is zero or the link is not being auto-negotiated,
+-	 * then {rx,tx}_pause force the driver to use/not-use pause
+-	 * flow control.
+-	 */
++	__u32	cmd;
+ 	__u32	autoneg;
+ 	__u32	rx_pause;
+ 	__u32	tx_pause;
+ };
+ 
+ #define ETH_GSTRING_LEN		32
++
++/**
++ * enum ethtool_stringset - string set ID
++ * @ETH_SS_TEST: Self-test result names, for use with %ETHTOOL_TEST
++ * @ETH_SS_STATS: Statistic names, for use with %ETHTOOL_GSTATS
++ * @ETH_SS_PRIV_FLAGS: Driver private flag names, for use with
++ *	%ETHTOOL_GPFLAGS and %ETHTOOL_SPFLAGS
++ * @ETH_SS_NTUPLE_FILTERS: Previously used with %ETHTOOL_GRXNTUPLE;
++ *	now deprecated
++ * @ETH_SS_FEATURES: Device feature names
++ */
+ enum ethtool_stringset {
+ 	ETH_SS_TEST		= 0,
+ 	ETH_SS_STATS,
+ 	ETH_SS_PRIV_FLAGS,
+-	ETH_SS_NTUPLE_FILTERS,	/* Do not use, GRXNTUPLE is now deprecated */
++	ETH_SS_NTUPLE_FILTERS,
+ 	ETH_SS_FEATURES,
+ };
+ 
+-/* for passing string sets for data tagging */
++/**
++ * struct ethtool_gstrings - string set for data tagging
++ * @cmd: Command number = %ETHTOOL_GSTRINGS
++ * @string_set: String set ID; one of &enum ethtool_stringset
++ * @len: On return, the number of strings in the string set
++ * @data: Buffer for strings.  Each string is null-padded to a size of
++ *	%ETH_GSTRING_LEN.
++ *
++ * Users must use %ETHTOOL_GSSET_INFO to find the number of strings in
++ * the string set.  They must allocate a buffer of the appropriate
++ * size immediately following this structure.
++ */
+ struct ethtool_gstrings {
+-	__u32	cmd;		/* ETHTOOL_GSTRINGS */
+-	__u32	string_set;	/* string set id e.c. ETH_SS_TEST, etc*/
+-	__u32	len;		/* number of strings in the string set */
++	__u32	cmd;
++	__u32	string_set;
++	__u32	len;
+ 	__u8	data[0];
+ };
+ 
++/**
++ * struct ethtool_sset_info - string set information
++ * @cmd: Command number = %ETHTOOL_GSSET_INFO
++ * @sset_mask: On entry, a bitmask of string sets to query, with bits
++ *	numbered according to &enum ethtool_stringset.  On return, a
++ *	bitmask of those string sets queried that are supported.
++ * @data: Buffer for string set sizes.  On return, this contains the
++ *	size of each string set that was queried and supported, in
++ *	order of ID.
++ *
++ * Example: The user passes in @sset_mask = 0x7 (sets 0, 1, 2) and on
++ * return @sset_mask == 0x6 (sets 1, 2).  Then @data[0] contains the
++ * size of set 1 and @data[1] contains the size of set 2.
++ *
++ * Users must allocate a buffer of the appropriate size (4 * number of
++ * sets queried) immediately following this structure.
++ */
+ struct ethtool_sset_info {
+-	__u32	cmd;		/* ETHTOOL_GSSET_INFO */
++	__u32	cmd;
+ 	__u32	reserved;
+-	__u64	sset_mask;	/* input: each bit selects an sset to query */
+-				/* output: each bit a returned sset */
+-	__u32	data[0];	/* ETH_SS_xxx count, in order, based on bits
+-				   in sset_mask.  One bit implies one
+-				   __u32, two bits implies two
+-				   __u32's, etc. */
++	__u64	sset_mask;
++	__u32	data[0];
+ };
+ 
+ /**
+@@ -393,24 +576,58 @@ enum ethtool_test_flags {
+ 	ETH_TEST_FL_EXTERNAL_LB_DONE	= (1 << 3),
+ };
+ 
+-/* for requesting NIC test and getting results*/
++/**
++ * struct ethtool_test - device self-test invocation
++ * @cmd: Command number = %ETHTOOL_TEST
++ * @flags: A bitmask of flags from &enum ethtool_test_flags.  Some
++ *	flags may be set by the user on entry; others may be set by
++ *	the driver on return.
++ * @len: On return, the number of test results
++ * @data: Array of test results
++ *
++ * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the
++ * number of test results that will be returned.  They must allocate a
++ * buffer of the appropriate size (8 * number of results) immediately
++ * following this structure.
++ */
+ struct ethtool_test {
+-	__u32	cmd;		/* ETHTOOL_TEST */
+-	__u32	flags;		/* ETH_TEST_FL_xxx */
++	__u32	cmd;
++	__u32	flags;
+ 	__u32	reserved;
+-	__u32	len;		/* result length, in number of u64 elements */
++	__u32	len;
+ 	__u64	data[0];
+ };
+ 
+-/* for dumping NIC-specific statistics */
++/**
++ * struct ethtool_stats - device-specific statistics
++ * @cmd: Command number = %ETHTOOL_GSTATS
++ * @n_stats: On return, the number of statistics
++ * @data: Array of statistics
++ *
++ * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the
++ * number of statistics that will be returned.  They must allocate a
++ * buffer of the appropriate size (8 * number of statistics)
++ * immediately following this structure.
++ */
+ struct ethtool_stats {
+-	__u32	cmd;		/* ETHTOOL_GSTATS */
+-	__u32	n_stats;	/* number of u64's being returned */
++	__u32	cmd;
++	__u32	n_stats;
+ 	__u64	data[0];
+ };
+ 
++/**
++ * struct ethtool_perm_addr - permanent hardware address
++ * @cmd: Command number = %ETHTOOL_GPERMADDR
++ * @size: On entry, the size of the buffer.  On return, the size of the
++ *	address.  The command fails if the buffer is too small.
++ * @data: Buffer for the address
++ *
++ * Users must allocate the buffer immediately following this structure.
++ * A buffer size of %MAX_ADDR_LEN should be sufficient for any address
++ * type.
++ */
+ struct ethtool_perm_addr {
+-	__u32	cmd;		/* ETHTOOL_GPERMADDR */
++	__u32	cmd;
+ 	__u32	size;
+ 	__u8	data[0];
+ };
+@@ -593,7 +810,7 @@ struct ethtool_rx_flow_spec {
+  * %ETHTOOL_SRXCLSRLINS may add the rule at any suitable unused
+  * location, and may remove a rule at a later location (lower
+  * priority) that matches exactly the same set of flows.  The special
+- * values are: %RX_CLS_LOC_ANY, selecting any location;
++ * values are %RX_CLS_LOC_ANY, selecting any location;
+  * %RX_CLS_LOC_FIRST, selecting the first suitable location (maximum
+  * priority); and %RX_CLS_LOC_LAST, selecting the last suitable
+  * location (minimum priority).  Additional special values may be
+@@ -630,6 +847,38 @@ struct ethtool_rxfh_indir {
+ };
+ 
+ /**
++ * struct ethtool_rxfh - command to get/set RX flow hash indir or/and hash key.
++ * @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH
++ * @rss_context: RSS context identifier.
++ * @indir_size: On entry, the array size of the user buffer for the
++ *	indirection table, which may be zero, or (for %ETHTOOL_SRSSH),
++ *	%ETH_RXFH_INDIR_NO_CHANGE.  On return from %ETHTOOL_GRSSH,
++ *	the array size of the hardware indirection table.
++ * @key_size: On entry, the array size of the user buffer for the hash key,
++ *	which may be zero.  On return from %ETHTOOL_GRSSH, the size of the
++ *	hardware hash key.
++ * @rsvd:	Reserved for future extensions.
++ * @rss_config: RX ring/queue index for each hash value i.e., indirection table
++ *	of @indir_size __u32 elements, followed by hash key of @key_size
++ *	bytes.
++ *
++ * For %ETHTOOL_GRSSH, a @indir_size and key_size of zero means that only the
++ * size should be returned.  For %ETHTOOL_SRSSH, an @indir_size of
++ * %ETH_RXFH_INDIR_NO_CHANGE means that indir table setting is not requested
++ * and a @indir_size of zero means the indir table should be reset to default
++ * values.
++ */
++struct ethtool_rxfh {
++	__u32   cmd;
++	__u32	rss_context;
++	__u32   indir_size;
++	__u32   key_size;
++	__u32	rsvd[2];
++	__u32   rss_config[0];
++};
++#define ETH_RXFH_INDIR_NO_CHANGE	0xffffffff
++
++/**
+  * struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter
+  * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW
+  * @h_u: Flow field values to match (dependent on @flow_type)
+@@ -704,9 +953,6 @@ struct ethtool_flash {
+  * 	 for %ETHTOOL_GET_DUMP_FLAG command
+  * @data: data collected for get dump data operation
+  */
+-
+-#define ETH_FW_DUMP_DISABLE 0
+-
+ struct ethtool_dump {
+ 	__u32	cmd;
+ 	__u32	version;
+@@ -715,6 +961,8 @@ struct ethtool_dump {
+ 	__u8	data[0];
+ };
+ 
++#define ETH_FW_DUMP_DISABLE 0
++
+ /* for returning and changing feature sets */
+ 
+ /**
+@@ -734,8 +982,9 @@ struct ethtool_get_features_block {
+ /**
+  * struct ethtool_gfeatures - command to get state of device's features
+  * @cmd: command number = %ETHTOOL_GFEATURES
+- * @size: in: number of elements in the features[] array;
+- *       out: number of elements in features[] needed to hold all features
++ * @size: On entry, the number of elements in the features[] array;
++ *	on return, the number of elements in features[] needed to hold
++ *	all features
+  * @features: state of features
+  */
+ struct ethtool_gfeatures {
+@@ -901,11 +1150,13 @@ enum ethtool_sfeatures_retval_bits {
+ #define ETHTOOL_GEEE		0x00000044 /* Get EEE settings */
+ #define ETHTOOL_SEEE		0x00000045 /* Set EEE settings */
+ 
++#define ETHTOOL_GRSSH		0x00000046 /* Get RX flow hash configuration */
++#define ETHTOOL_SRSSH		0x00000047 /* Set RX flow hash configuration */
++
+ /* compatibility with older code */
+ #define SPARC_ETH_GSET		ETHTOOL_GSET
+ #define SPARC_ETH_SSET		ETHTOOL_SSET
+ 
+-/* Indicates what features are supported by the interface. */
+ #define SUPPORTED_10baseT_Half		(1 << 0)
+ #define SUPPORTED_10baseT_Full		(1 << 1)
+ #define SUPPORTED_100baseT_Half		(1 << 2)
+@@ -934,7 +1185,6 @@ enum ethtool_sfeatures_retval_bits {
+ #define SUPPORTED_40000baseSR4_Full	(1 << 25)
+ #define SUPPORTED_40000baseLR4_Full	(1 << 26)
+ 
+-/* Indicates what features are advertised by the interface. */
+ #define ADVERTISED_10baseT_Half		(1 << 0)
+ #define ADVERTISED_10baseT_Full		(1 << 1)
+ #define ADVERTISED_100baseT_Half	(1 << 2)
+@@ -993,15 +1243,13 @@ enum ethtool_sfeatures_retval_bits {
+ #define PORT_OTHER		0xff
+ 
+ /* Which transceiver to use. */
+-#define XCVR_INTERNAL		0x00
+-#define XCVR_EXTERNAL		0x01
++#define XCVR_INTERNAL		0x00 /* PHY and MAC are in the same package */
++#define XCVR_EXTERNAL		0x01 /* PHY and MAC are in different packages */
+ #define XCVR_DUMMY1		0x02
+ #define XCVR_DUMMY2		0x03
+ #define XCVR_DUMMY3		0x04
+ 
+-/* Enable or disable autonegotiation.  If this is set to enable,
+- * the forced link modes above are completely ignored.
+- */
++/* Enable or disable autonegotiation. */
+ #define AUTONEG_DISABLE		0x00
+ #define AUTONEG_ENABLE		0x01
+ 
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0002-Report-Backplane-as-supported-port.patch b/SOURCES/0002-Report-Backplane-as-supported-port.patch
deleted file mode 100644
index 8eb776c..0000000
--- a/SOURCES/0002-Report-Backplane-as-supported-port.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From e4e9f69dbcb55c4dca2323dce2e89edfa6e28ec4 Mon Sep 17 00:00:00 2001
-From: Ivan Vecera <ivecera@redhat.com>
-Date: Thu, 20 Feb 2014 18:48:56 +0100
-Subject: [PATCH 2/2] ethtool: Report Backplane as supported port
-
-Signed-off-by: Ivan Vecera <ivecera@redhat.com>
-Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
----
- ethtool.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/ethtool.c b/ethtool.c
-index 8cc10b5..658a7b2 100644
---- a/ethtool.c
-+++ b/ethtool.c
-@@ -485,6 +485,8 @@ static void dump_supported(struct ethtool_cmd *ep)
- 		fprintf(stdout, "MII ");
- 	if (mask & SUPPORTED_FIBRE)
- 		fprintf(stdout, "FIBRE ");
-+	if (mask & SUPPORTED_Backplane)
-+		fprintf(stdout, "Backplane ");
- 	fprintf(stdout, "]\n");
- 
- 	dump_link_caps("Supported", "Supports", mask, 0);
--- 
-1.8.3.1
-
diff --git a/SOURCES/0002-Support-for-configurable-RSS-hash-key.patch b/SOURCES/0002-Support-for-configurable-RSS-hash-key.patch
new file mode 100644
index 0000000..c69a995
--- /dev/null
+++ b/SOURCES/0002-Support-for-configurable-RSS-hash-key.patch
@@ -0,0 +1,575 @@
+From 86c0326c06b2de611f438a453fae51512747e831 Mon Sep 17 00:00:00 2001
+From: Venkat Duvvuru <VenkatKumar.Duvvuru@Emulex.com>
+Date: Tue, 22 Jul 2014 17:51:07 +0530
+Subject: [PATCH 2/4] ethtool: Support for configurable RSS hash key
+
+This ethtool patch will primarily implement the parser for the options provided
+by the user for get and set rxfh before invoking the ioctl.
+This patch also has
+1. Ethtool man page changes which describes the Usage of
+   get and set rxfh options.
+2. Test cases for get and set rxfh in test-cmdline.c
+
+Signed-off-by: Venkat Duvvuru <VenkatKumar.Duvvuru@Emulex.com>
+---
+ ethtool.8.in   |  18 ++-
+ ethtool.c      | 393 ++++++++++++++++++++++++++++++++++++++++++++++++---------
+ test-cmdline.c |  11 ++
+ 3 files changed, 354 insertions(+), 68 deletions(-)
+
+diff --git a/ethtool.8.in b/ethtool.8.in
+index bb394cc..c1e6e09 100644
+--- a/ethtool.8.in
++++ b/ethtool.8.in
+@@ -286,11 +286,12 @@ ethtool \- query or control network driver and hardware settings
+ .B ethtool \-T|\-\-show\-time\-stamping
+ .I devname
+ .HP
+-.B ethtool \-x|\-\-show\-rxfh\-indir
++.B ethtool \-x|\-\-show\-rxfh\-indir|\-\-show\-rxfh
+ .I devname
+ .HP
+-.B ethtool \-X|\-\-set\-rxfh\-indir
++.B ethtool \-X|\-\-set\-rxfh\-indir|\-\-rxfh
+ .I devname
++.RB [ hkey \ \*(MA:\...]
+ .RB [\  equal
+ .IR N \ |
+ .BI weight\  W0
+@@ -784,11 +785,16 @@ Sets the dump flag for the device.
+ Show the device's time stamping capabilities and associated PTP
+ hardware clock.
+ .TP
+-.B \-x \-\-show\-rxfh\-indir
+-Retrieves the receive flow hash indirection table.
++.B \-x \-\-show\-rxfh\-indir \-\-show\-rxfh
++Retrieves the receive flow hash indirection table and/or RSS hash key.
+ .TP
+-.B \-X \-\-set\-rxfh\-indir
+-Configures the receive flow hash indirection table.
++.B \-X \-\-set\-rxfh\-indir \-\-rxfh
++Configures the receive flow hash indirection table and/or RSS hash key.
++.TP
++.BI hkey
++Sets RSS hash key of the specified network device. RSS hash key should be of device supported length.
++Hash key format must be in xx:yy:zz:aa:bb:cc format meaning both the nibbles of a byte should be mentioned
++even if a nibble is zero.
+ .TP
+ .BI equal\  N
+ Sets the receive flow hash indirection table to spread flows evenly
+diff --git a/ethtool.c b/ethtool.c
+index 19b8b0c..bf583f3 100644
+--- a/ethtool.c
++++ b/ethtool.c
+@@ -878,6 +878,74 @@ static char *unparse_rxfhashopts(u64 opts)
+ 	return buf;
+ }
+ 
++static int convert_string_to_hashkey(char *rss_hkey, u32 key_size,
++				     const char *rss_hkey_string)
++{
++	u32 i = 0;
++	int hex_byte, len;
++
++	do {
++		if (i > (key_size - 1)) {
++			fprintf(stderr,
++				"Key is too long for device (%u > %u)\n",
++				i + 1, key_size);
++			goto err;
++		}
++
++		if (sscanf(rss_hkey_string, "%2x%n", &hex_byte, &len) < 1 ||
++		    len != 2) {
++			fprintf(stderr, "Invalid RSS hash key format\n");
++			goto err;
++		}
++
++		rss_hkey[i++] = hex_byte;
++		rss_hkey_string += 2;
++
++		if (*rss_hkey_string == ':') {
++			rss_hkey_string++;
++		} else if (*rss_hkey_string != '\0') {
++			fprintf(stderr, "Invalid RSS hash key format\n");
++			goto err;
++		}
++
++	} while (*rss_hkey_string);
++
++	if (i != key_size) {
++		fprintf(stderr, "Key is too short for device (%u < %u)\n",
++			i, key_size);
++		goto err;
++	}
++
++	return 0;
++err:
++	return 2;
++}
++
++static int parse_hkey(char **rss_hkey, u32 key_size,
++		      const char *rss_hkey_string)
++{
++	if (!key_size) {
++		fprintf(stderr,
++			"Cannot set RX flow hash configuration:\n"
++			" Hash key setting not supported\n");
++		return 1;
++	}
++
++	*rss_hkey = malloc(key_size);
++	if (!(*rss_hkey)) {
++		perror("Cannot allocate memory for RSS hash key");
++		return 1;
++	}
++
++	if (convert_string_to_hashkey(*rss_hkey, key_size,
++				      rss_hkey_string)) {
++		free(*rss_hkey);
++		*rss_hkey = NULL;
++		return 2;
++	}
++	return 0;
++}
++
+ static const struct {
+ 	const char *name;
+ 	int (*func)(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
+@@ -3042,92 +3110,141 @@ static int do_grxclass(struct cmd_context *ctx)
+ 	return err ? 1 : 0;
+ }
+ 
+-static int do_grxfhindir(struct cmd_context *ctx)
++static void print_indir_table(struct cmd_context *ctx,
++			      struct ethtool_rxnfc *ring_count,
++			      u32 indir_size, u32 *indir)
+ {
+-	struct ethtool_rxnfc ring_count;
+-	struct ethtool_rxfh_indir indir_head;
+-	struct ethtool_rxfh_indir *indir;
+ 	u32 i;
+-	int err;
+ 
+-	ring_count.cmd = ETHTOOL_GRXRINGS;
+-	err = send_ioctl(ctx, &ring_count);
+-	if (err < 0) {
+-		perror("Cannot get RX ring count");
+-		return 102;
++	printf("RX flow hash indirection table for %s with %llu RX ring(s):\n",
++	       ctx->devname, ring_count->data);
++
++	if (!indir_size)
++		printf("Operation not supported\n");
++
++	for (i = 0; i < indir_size; i++) {
++		if (i % 8 == 0)
++			printf("%5u: ", i);
++		printf(" %5u", indir[i]);
++		if (i % 8 == 7)
++			fputc('\n', stdout);
+ 	}
++}
++
++static int do_grxfhindir(struct cmd_context *ctx,
++			 struct ethtool_rxnfc *ring_count)
++{
++	struct ethtool_rxfh_indir indir_head;
++	struct ethtool_rxfh_indir *indir;
++	int err;
+ 
+ 	indir_head.cmd = ETHTOOL_GRXFHINDIR;
+ 	indir_head.size = 0;
+ 	err = send_ioctl(ctx, &indir_head);
+ 	if (err < 0) {
+ 		perror("Cannot get RX flow hash indirection table size");
+-		return 103;
++		return 1;
+ 	}
+ 
+ 	indir = malloc(sizeof(*indir) +
+ 		       indir_head.size * sizeof(*indir->ring_index));
++	if (!indir) {
++		perror("Cannot allocate memory for indirection table");
++		return 1;
++	}
++
+ 	indir->cmd = ETHTOOL_GRXFHINDIR;
+ 	indir->size = indir_head.size;
+ 	err = send_ioctl(ctx, indir);
+ 	if (err < 0) {
+ 		perror("Cannot get RX flow hash indirection table");
+-		return 103;
++		free(indir);
++		return 1;
+ 	}
+ 
+-	printf("RX flow hash indirection table for %s with %llu RX ring(s):\n",
+-	       ctx->devname, ring_count.data);
+-	for (i = 0; i < indir->size; i++) {
+-		if (i % 8 == 0)
+-			printf("%5u: ", i);
+-		printf(" %5u", indir->ring_index[i]);
+-		if (i % 8 == 7)
+-			fputc('\n', stdout);
+-	}
++	print_indir_table(ctx, ring_count, indir->size, indir->ring_index);
++
++	free(indir);
+ 	return 0;
+ }
+ 
+-static int do_srxfhindir(struct cmd_context *ctx)
++static int do_grxfh(struct cmd_context *ctx)
+ {
+-	int rxfhindir_equal = 0;
+-	char **rxfhindir_weight = NULL;
+-	struct ethtool_rxfh_indir indir_head;
+-	struct ethtool_rxfh_indir *indir;
+-	u32 i;
++	struct ethtool_rxfh rss_head = {0};
++	struct ethtool_rxnfc ring_count;
++	struct ethtool_rxfh *rss;
++	u32 i, indir_bytes;
++	char *hkey;
+ 	int err;
+ 
+-	if (ctx->argc < 2)
+-		exit_bad_args();
+-	if (!strcmp(ctx->argp[0], "equal")) {
+-		if (ctx->argc != 2)
+-			exit_bad_args();
+-		rxfhindir_equal = get_int_range(ctx->argp[1], 0, 1, INT_MAX);
+-	} else if (!strcmp(ctx->argp[0], "weight")) {
+-		rxfhindir_weight = ctx->argp + 1;
+-	} else {
+-		exit_bad_args();
++	ring_count.cmd = ETHTOOL_GRXRINGS;
++	err = send_ioctl(ctx, &ring_count);
++	if (err < 0) {
++		perror("Cannot get RX ring count");
++		return 1;
+ 	}
+ 
+-	indir_head.cmd = ETHTOOL_GRXFHINDIR;
+-	indir_head.size = 0;
+-	err = send_ioctl(ctx, &indir_head);
++	rss_head.cmd = ETHTOOL_GRSSH;
++	err = send_ioctl(ctx, &rss_head);
++	if (err < 0 && errno == EOPNOTSUPP) {
++		return do_grxfhindir(ctx, &ring_count);
++	} else if (err < 0) {
++		perror("Cannot get RX flow hash indir size and/or key size");
++		return 1;
++	}
++
++	rss = calloc(1, sizeof(*rss) +
++			rss_head.indir_size * sizeof(rss_head.rss_config[0]) +
++			rss_head.key_size);
++	if (!rss) {
++		perror("Cannot allocate memory for RX flow hash config");
++		return 1;
++	}
++
++	rss->cmd = ETHTOOL_GRSSH;
++	rss->indir_size = rss_head.indir_size;
++	rss->key_size = rss_head.key_size;
++	err = send_ioctl(ctx, rss);
+ 	if (err < 0) {
+-		perror("Cannot get RX flow hash indirection table size");
+-		return 104;
++		perror("Cannot get RX flow hash configuration");
++		free(rss);
++		return 1;
+ 	}
+ 
+-	indir = malloc(sizeof(*indir) +
+-		       indir_head.size * sizeof(*indir->ring_index));
+-	indir->cmd = ETHTOOL_SRXFHINDIR;
+-	indir->size = indir_head.size;
++	print_indir_table(ctx, &ring_count, rss->indir_size, rss->rss_config);
++
++	indir_bytes = rss->indir_size * sizeof(rss->rss_config[0]);
++	hkey = ((char *)rss->rss_config + indir_bytes);
+ 
++	printf("RSS hash key:\n");
++	if (!rss->key_size)
++		printf("Operation not supported\n");
++
++	for (i = 0; i < rss->key_size; i++) {
++		if (i == (rss->key_size - 1))
++			printf("%02x\n", (u8) hkey[i]);
++		else
++			printf("%02x:", (u8) hkey[i]);
++	}
++
++	free(rss);
++	return 0;
++}
++
++static int fill_indir_table(u32 *indir_size, u32 *indir, int rxfhindir_equal,
++			    char **rxfhindir_weight, u32 num_weights)
++{
++	u32 i;
++	/*
++	 * "*indir_size == 0" ==> reset indir to default
++	 */
+ 	if (rxfhindir_equal) {
+-		for (i = 0; i < indir->size; i++)
+-			indir->ring_index[i] = i % rxfhindir_equal;
+-	} else {
++		for (i = 0; i < *indir_size; i++)
++			indir[i] = i % rxfhindir_equal;
++	} else if (rxfhindir_weight) {
+ 		u32 j, weight, sum = 0, partial = 0;
+ 
+-		for (j = 0; rxfhindir_weight[j]; j++) {
++		for (j = 0; j < num_weights; j++) {
+ 			weight = get_u32(rxfhindir_weight[j], 0);
+ 			sum += weight;
+ 		}
+@@ -3135,36 +3252,187 @@ static int do_srxfhindir(struct cmd_context *ctx)
+ 		if (sum == 0) {
+ 			fprintf(stderr,
+ 				"At least one weight must be non-zero\n");
+-			exit(1);
++			return 2;
+ 		}
+ 
+-		if (sum > indir->size) {
++		if (sum > *indir_size) {
+ 			fprintf(stderr,
+ 				"Total weight exceeds the size of the "
+ 				"indirection table\n");
+-			exit(1);
++			return 2;
+ 		}
+ 
+ 		j = -1;
+-		for (i = 0; i < indir->size; i++) {
+-			while (i >= indir->size * partial / sum) {
++		for (i = 0; i < *indir_size; i++) {
++			while (i >= (*indir_size) * partial / sum) {
+ 				j += 1;
+ 				weight = get_u32(rxfhindir_weight[j], 0);
+ 				partial += weight;
+ 			}
+-			indir->ring_index[i] = j;
++			indir[i] = j;
+ 		}
++	} else {
++		*indir_size = ETH_RXFH_INDIR_NO_CHANGE;
++	}
++
++	return 0;
++}
++
++static int do_srxfhindir(struct cmd_context *ctx, int rxfhindir_equal,
++			 char **rxfhindir_weight, u32 num_weights)
++{
++	struct ethtool_rxfh_indir indir_head;
++	struct ethtool_rxfh_indir *indir;
++	int err;
++
++	indir_head.cmd = ETHTOOL_GRXFHINDIR;
++	indir_head.size = 0;
++	err = send_ioctl(ctx, &indir_head);
++	if (err < 0) {
++		perror("Cannot get RX flow hash indirection table size");
++		return 1;
++	}
++
++	indir = malloc(sizeof(*indir) +
++		       indir_head.size * sizeof(*indir->ring_index));
++
++	if (!indir) {
++		perror("Cannot allocate memory for indirection table");
++		return 1;
++	}
++
++	indir->cmd = ETHTOOL_SRXFHINDIR;
++	indir->size = indir_head.size;
++
++	if (fill_indir_table(&indir->size, indir->ring_index, rxfhindir_equal,
++			     rxfhindir_weight, num_weights)) {
++		free(indir);
++		return 1;
+ 	}
+ 
+ 	err = send_ioctl(ctx, indir);
+ 	if (err < 0) {
+ 		perror("Cannot set RX flow hash indirection table");
+-		return 105;
++		free(indir);
++		return 1;
+ 	}
+ 
++	free(indir);
+ 	return 0;
+ }
+ 
++static int do_srxfh(struct cmd_context *ctx)
++{
++	struct ethtool_rxfh rss_head = {0};
++	struct ethtool_rxfh *rss;
++	struct ethtool_rxnfc ring_count;
++	int rxfhindir_equal = 0;
++	char **rxfhindir_weight = NULL;
++	char *rxfhindir_key = NULL;
++	char *hkey = NULL;
++	int err = 0;
++	u32 arg_num = 0, indir_bytes = 0;
++	u32 entry_size = sizeof(rss_head.rss_config[0]);
++	u32 num_weights = 0;
++
++	if (ctx->argc < 2)
++		exit_bad_args();
++
++	while (arg_num < ctx->argc) {
++		if (!strcmp(ctx->argp[arg_num], "equal")) {
++			++arg_num;
++			rxfhindir_equal = get_int_range(ctx->argp[arg_num],
++							0, 1, INT_MAX);
++			++arg_num;
++		} else if (!strcmp(ctx->argp[arg_num], "weight")) {
++			++arg_num;
++			rxfhindir_weight = ctx->argp + arg_num;
++			while (arg_num < ctx->argc &&
++			       isdigit((unsigned char)ctx->argp[arg_num][0])) {
++				++arg_num;
++				++num_weights;
++			}
++			if (!num_weights)
++				exit_bad_args();
++		} else if (!strcmp(ctx->argp[arg_num], "hkey")) {
++			++arg_num;
++			rxfhindir_key = ctx->argp[arg_num];
++			if (!rxfhindir_key)
++				exit_bad_args();
++			++arg_num;
++		} else {
++			exit_bad_args();
++		}
++	}
++
++	if (rxfhindir_equal && rxfhindir_weight) {
++		fprintf(stderr,
++			"Equal and weight options are mutually exclusive\n");
++		return 1;
++	}
++
++	ring_count.cmd = ETHTOOL_GRXRINGS;
++	err = send_ioctl(ctx, &ring_count);
++	if (err < 0) {
++		perror("Cannot get RX ring count");
++		return 1;
++	}
++
++	rss_head.cmd = ETHTOOL_GRSSH;
++	err = send_ioctl(ctx, &rss_head);
++	if (err < 0 && errno == EOPNOTSUPP && !rxfhindir_key) {
++		return do_srxfhindir(ctx, rxfhindir_equal, rxfhindir_weight,
++				     num_weights);
++	} else if (err < 0) {
++		perror("Cannot get RX flow hash indir size and key size");
++		return 1;
++	}
++
++	if (rxfhindir_key) {
++		err = parse_hkey(&hkey, rss_head.key_size,
++				 rxfhindir_key);
++		if (err)
++			return err;
++	}
++
++	if (rxfhindir_equal || rxfhindir_weight)
++		indir_bytes = rss_head.indir_size * entry_size;
++
++	rss = calloc(1, sizeof(*rss) + indir_bytes + rss_head.key_size);
++	if (!rss) {
++		perror("Cannot allocate memory for RX flow hash config");
++		return 1;
++	}
++	rss->cmd = ETHTOOL_SRSSH;
++	rss->indir_size = rss_head.indir_size;
++	rss->key_size = rss_head.key_size;
++
++	if (fill_indir_table(&rss->indir_size, rss->rss_config, rxfhindir_equal,
++			     rxfhindir_weight, num_weights)) {
++		err = 1;
++		goto free;
++	}
++
++	if (hkey)
++		memcpy((char *)rss->rss_config + indir_bytes,
++		       hkey, rss->key_size);
++	else
++		rss->key_size = 0;
++
++	err = send_ioctl(ctx, rss);
++	if (err < 0) {
++		perror("Cannot set RX flow hash configuration");
++		err = 1;
++	}
++
++free:
++	if (hkey)
++		free(hkey);
++
++	free(rss);
++	return err;
++}
++
+ static int do_flash(struct cmd_context *ctx)
+ {
+ 	char *flash_file;
+@@ -3842,11 +4110,12 @@ static const struct option {
+ 	  "		delete %d\n" },
+ 	{ "-T|--show-time-stamping", 1, do_tsinfo,
+ 	  "Show time stamping capabilities" },
+-	{ "-x|--show-rxfh-indir", 1, do_grxfhindir,
+-	  "Show Rx flow hash indirection" },
+-	{ "-X|--set-rxfh-indir", 1, do_srxfhindir,
+-	  "Set Rx flow hash indirection",
+-	  "		equal N | weight W0 W1 ...\n" },
++	{ "-x|--show-rxfh-indir|--show-rxfh", 1, do_grxfh,
++	  "Show Rx flow hash indirection and/or 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"
++	  "		[ 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",
+ 	  "               FILENAME [ REGION-NUMBER-TO-FLASH ]\n" },
+diff --git a/test-cmdline.c b/test-cmdline.c
+index f1d4555..be41a30 100644
+--- a/test-cmdline.c
++++ b/test-cmdline.c
+@@ -173,6 +173,7 @@ static struct test_case {
+ 	{ 1, "-T" },
+ 	{ 0, "-x devname" },
+ 	{ 0, "--show-rxfh-indir devname" },
++	{ 0, "--show-rxfh devname" },
+ 	{ 1, "-x" },
+ 	/* Argument parsing for -X is specialised */
+ 	{ 0, "-X devname equal 2" },
+@@ -181,6 +182,16 @@ static struct test_case {
+ 	{ 1, "--set-rxfh-indir devname equal foo" },
+ 	{ 1, "-X devname equal" },
+ 	{ 0, "--set-rxfh-indir devname weight 1 2 3 4" },
++	{ 0, "--rxfh devname hkey 48:15:6e:bb:d8:bd:6f:b1:a4:c6:7a:c4:76:1c:29:98:da:e1:ae:6c:2e:12:2f:c0:b9:be:61:3d:00:54:35:9e:09:05:c7:d7:93:72:4a:ee" },
++	{ 0, "-X devname hkey 48:15:6e:bb:d8:bd:6f:b1:a4:c6:7a:c4:76:1c:29:98:da:e1:ae:6c:2e:12:2f:c0:b9:be:61:3d:00:54:35:9e:09:05:c7:d7:93:72:4a:ee" },
++	{ 1, "--rxfh devname hkey foo" },
++	{ 1, "-X devname hkey foo" },
++	{ 0, "--rxfh devname hkey 48:15:6e:bb:d8:bd:6f:b1:a4:c6:7a:c4:76:1c:29:98:da:e1:ae:6c:2e:12:2f:c0:b9:be:61:3d:00:54:35:9e:09:05:c7:d7:93:72:4a:ee weight 1 2 3 4" },
++	{ 0, "-X devname weight 1 2 3 4 hkey 48:15:6e:bb:d8:bd:6f:b1:a4:c6:7a:c4:76:1c:29:98:da:e1:ae:6c:2e:12:2f:c0:b9:be:61:3d:00:54:35:9e:09:05:c7:d7:93:72:4a:ee" },
++	{ 0, "--rxfh devname hkey 48:15:6e:bb:d8:bd:6f:b1:a4:c6:7a:c4:76:1c:29:98:da:e1:ae:6c:2e:12:2f:c0:b9:be:61:3d:00:54:35:9e:09:05:c7:d7:93:72:4a:ee equal 2" },
++	{ 0, "-X devname equal 2 hkey 48:15:6e:bb:d8:bd:6f:b1:a4:c6:7a:c4:76:1c:29:98:da:e1:ae:6c:2e:12:2f:c0:b9:be:61:3d:00:54:35:9e:09:05:c7:d7:93:72:4a:ee" },
++	{ 1, "--rxfh devname weight 1 2 3 4 equal 8" },
++	{ 1, "-X devname weight 1 2 3 4 equal 8" },
+ 	{ 1, "-X devname foo" },
+ 	{ 1, "-X" },
+ 	{ 0, "-P devname" },
+-- 
+1.8.3.1
+
diff --git a/SOURCES/0003-Disable-test-cases-for-rxfh-hash-key-pa.patch b/SOURCES/0003-Disable-test-cases-for-rxfh-hash-key-pa.patch
new file mode 100644
index 0000000..7665712
--- /dev/null
+++ b/SOURCES/0003-Disable-test-cases-for-rxfh-hash-key-pa.patch
@@ -0,0 +1,39 @@
+From 14ef76c155ad0d646f5c2d0fdfa31edacd4024c6 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sun, 21 Sep 2014 23:40:29 +0100
+Subject: [PATCH 3/4] test-cmdline: Disable test cases for --rxfh hash key
+ parsing
+
+test-cmdline does not mock the result of send_ioctl() but just treats
+a call to send_ioctl() as indicating successful parsing.  Any parse
+failure after this point cannot be tested for.  Currently, the hash
+key string passed to --rxfh isn't parsed until after the device's key
+size is known, so we can't test it tis way.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ test-cmdline.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/test-cmdline.c b/test-cmdline.c
+index be41a30..2fd7cbb 100644
+--- a/test-cmdline.c
++++ b/test-cmdline.c
+@@ -184,8 +184,14 @@ static struct test_case {
+ 	{ 0, "--set-rxfh-indir devname weight 1 2 3 4" },
+ 	{ 0, "--rxfh devname hkey 48:15:6e:bb:d8:bd:6f:b1:a4:c6:7a:c4:76:1c:29:98:da:e1:ae:6c:2e:12:2f:c0:b9:be:61:3d:00:54:35:9e:09:05:c7:d7:93:72:4a:ee" },
+ 	{ 0, "-X devname hkey 48:15:6e:bb:d8:bd:6f:b1:a4:c6:7a:c4:76:1c:29:98:da:e1:ae:6c:2e:12:2f:c0:b9:be:61:3d:00:54:35:9e:09:05:c7:d7:93:72:4a:ee" },
++#if 0
++	/* XXX These won't fail as expected because we don't parse the
++	 * hash key until after the first send_ioctl().  That needs to
++	 * be changed before we enable them.
++	 */
+ 	{ 1, "--rxfh devname hkey foo" },
+ 	{ 1, "-X devname hkey foo" },
++#endif
+ 	{ 0, "--rxfh devname hkey 48:15:6e:bb:d8:bd:6f:b1:a4:c6:7a:c4:76:1c:29:98:da:e1:ae:6c:2e:12:2f:c0:b9:be:61:3d:00:54:35:9e:09:05:c7:d7:93:72:4a:ee weight 1 2 3 4" },
+ 	{ 0, "-X devname weight 1 2 3 4 hkey 48:15:6e:bb:d8:bd:6f:b1:a4:c6:7a:c4:76:1c:29:98:da:e1:ae:6c:2e:12:2f:c0:b9:be:61:3d:00:54:35:9e:09:05:c7:d7:93:72:4a:ee" },
+ 	{ 0, "--rxfh devname hkey 48:15:6e:bb:d8:bd:6f:b1:a4:c6:7a:c4:76:1c:29:98:da:e1:ae:6c:2e:12:2f:c0:b9:be:61:3d:00:54:35:9e:09:05:c7:d7:93:72:4a:ee equal 2" },
+-- 
+1.8.3.1
+
diff --git a/SPECS/ethtool.spec b/SPECS/ethtool.spec
index 6f94055..8ddf0b5 100644
--- a/SPECS/ethtool.spec
+++ b/SPECS/ethtool.spec
@@ -1,7 +1,7 @@
 Name:		ethtool
 Epoch:		2
-Version:	3.8
-Release:	4%{?dist}
+Version:	3.15
+Release:	2%{?dist}
 Summary:	Settings tool for Ethernet NICs
 
 License:	GPLv2
@@ -21,8 +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-Add-string-to-display-support-for-KR-PHY.patch
-Patch1:		0002-Report-Backplane-as-supported-port.patch
+Patch0:		0001-ethtool-copy.h-sync-with-net.patch
+Patch1:		0002-Support-for-configurable-RSS-hash-key.patch
+Patch2:		0003-Disable-test-cases-for-rxfh-hash-key-pa.patch
 
 %description
 This utility allows querying and changing settings such as speed,
@@ -33,6 +34,7 @@ network devices, especially of Ethernet devices.
 %setup -q
 %patch0 -p1
 %patch1 -p1
+%patch2 -p1
 
 # Only needed when using upstream git
 # aclocal
@@ -53,8 +55,11 @@ make DESTDIR=%{buildroot} INSTALL='install -p' install
 %{_mandir}/man8/%{name}.8*
 
 %changelog
-* Wed Oct  1 2014 Ivan Vecera <ivecera@redhat.com> - 2:3.8-4
-- Resolves: bz#1141736
+* Fri Oct 31 2014 Ivan Vecera <ivecera@redhat.com> - 2:3.15-2
+- Support for configurable RSS hash key
+
+* Mon Sep 15 2014 Ivan Vecera <ivecera@redhat.com> - 2:3.15-1
+- Update to the latest upstream
 
 * Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 2:3.8-3
 - Mass rebuild 2014-01-24