summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/e1000e/ethtool.c
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2012-01-11 01:26:50 +0000
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2012-01-25 23:11:55 -0800
commit70495a500d787c0c90a136acf454cb7d0eecd82e (patch)
treeb84a478b2e33ed628043638b6bf2aff46c1c5720 /drivers/net/ethernet/intel/e1000e/ethtool.c
parentafd12939a09ca8f96cf8349c913dc143471c9b3c (diff)
e1000e: add Receive Packet Steering (RPS) support
Enable RPS by default. Disallow jumbo frames when both receive checksum and receive hashing are enabled because the hardware cannot do both IP payload checksum (enabled when receive checksum is enabled when using packet split which is used for jumbo frames) and provide RSS hash at the same time. v2: added ethtool command to query flow hashing behavior per Ben Hutchings and changed the type of rsskey to cleanup the setting of the register array and avoid unnecessary casts (as pointed out by Joe Perches). The long error messages are not changed since there is nothing in the kernel ./Documentation that suggests the preferred method for dealing with long messages other than to never break strings; leaving them as-is for now. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/e1000e/ethtool.c')
-rw-r--r--drivers/net/ethernet/intel/e1000e/ethtool.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index fb2c28e799a..0a3137a791e 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -1955,6 +1955,53 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset,
}
}
+static int e1000_get_rxnfc(struct net_device *netdev,
+ struct ethtool_rxnfc *info, u32 *rule_locs)
+{
+ info->data = 0;
+
+ switch (info->cmd) {
+ case ETHTOOL_GRXFH: {
+ struct e1000_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ u32 mrqc = er32(MRQC);
+
+ if (!(mrqc & E1000_MRQC_RSS_FIELD_MASK))
+ return 0;
+
+ switch (info->flow_type) {
+ case TCP_V4_FLOW:
+ if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_TCP)
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ /* fall through */
+ case UDP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ case AH_ESP_V4_FLOW:
+ case IPV4_FLOW:
+ if (mrqc & E1000_MRQC_RSS_FIELD_IPV4)
+ info->data |= RXH_IP_SRC | RXH_IP_DST;
+ break;
+ case TCP_V6_FLOW:
+ if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP)
+ info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+ /* fall through */
+ case UDP_V6_FLOW:
+ case SCTP_V6_FLOW:
+ case AH_ESP_V6_FLOW:
+ case IPV6_FLOW:
+ if (mrqc & E1000_MRQC_RSS_FIELD_IPV6)
+ info->data |= RXH_IP_SRC | RXH_IP_DST;
+ break;
+ default:
+ break;
+ }
+ return 0;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static const struct ethtool_ops e1000_ethtool_ops = {
.get_settings = e1000_get_settings,
.set_settings = e1000_set_settings,
@@ -1981,6 +2028,7 @@ static const struct ethtool_ops e1000_ethtool_ops = {
.get_sset_count = e1000e_get_sset_count,
.get_coalesce = e1000_get_coalesce,
.set_coalesce = e1000_set_coalesce,
+ .get_rxnfc = e1000_get_rxnfc,
};
void e1000e_set_ethtool_ops(struct net_device *netdev)