aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2012-02-08 02:51:53 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2012-03-19 05:03:15 -0400
commitef6afc0caceebb3b49cd384f8c634f89f5089997 (patch)
treefd95d484357deca295bad8ab978e8a5d137590c8 /drivers/net/ethernet
parent581330ba7b219fec0587452bd72fe5635c30c4ae (diff)
ixgbe: Add support for enabling UDP RSS via the ethtool rx-flow-hash command
This patch adds support for enabling or disabling UDP RSS via the ethtool -N rx-flow-hash command. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Tested-by: Stephen Ko <stephen.s.ko@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h3
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c153
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c5
3 files changed, 160 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 862041419635..4ceac3a09d09 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -438,7 +438,8 @@ struct ixgbe_adapter {
438#define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 5) 438#define IXGBE_FLAG2_SFP_NEEDS_RESET (u32)(1 << 5)
439#define IXGBE_FLAG2_RESET_REQUESTED (u32)(1 << 6) 439#define IXGBE_FLAG2_RESET_REQUESTED (u32)(1 << 6)
440#define IXGBE_FLAG2_FDIR_REQUIRES_REINIT (u32)(1 << 7) 440#define IXGBE_FLAG2_FDIR_REQUIRES_REINIT (u32)(1 << 7)
441 441#define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP (u32)(1 << 8)
442#define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP (u32)(1 << 9)
442 443
443 /* Tx fast path data */ 444 /* Tx fast path data */
444 int num_tx_queues; 445 int num_tx_queues;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index b09e67cc9d6e..b64d8a2adb42 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -2328,6 +2328,48 @@ static int ixgbe_get_ethtool_fdir_all(struct ixgbe_adapter *adapter,
2328 return 0; 2328 return 0;
2329} 2329}
2330 2330
2331static int ixgbe_get_rss_hash_opts(struct ixgbe_adapter *adapter,
2332 struct ethtool_rxnfc *cmd)
2333{
2334 cmd->data = 0;
2335
2336 /* if RSS is disabled then report no hashing */
2337 if (!(adapter->flags & IXGBE_FLAG_RSS_ENABLED))
2338 return 0;
2339
2340 /* Report default options for RSS on ixgbe */
2341 switch (cmd->flow_type) {
2342 case TCP_V4_FLOW:
2343 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
2344 case UDP_V4_FLOW:
2345 if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV4_UDP)
2346 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
2347 case SCTP_V4_FLOW:
2348 case AH_ESP_V4_FLOW:
2349 case AH_V4_FLOW:
2350 case ESP_V4_FLOW:
2351 case IPV4_FLOW:
2352 cmd->data |= RXH_IP_SRC | RXH_IP_DST;
2353 break;
2354 case TCP_V6_FLOW:
2355 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
2356 case UDP_V6_FLOW:
2357 if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP)
2358 cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
2359 case SCTP_V6_FLOW:
2360 case AH_ESP_V6_FLOW:
2361 case AH_V6_FLOW:
2362 case ESP_V6_FLOW:
2363 case IPV6_FLOW:
2364 cmd->data |= RXH_IP_SRC | RXH_IP_DST;
2365 break;
2366 default:
2367 return -EINVAL;
2368 }
2369
2370 return 0;
2371}
2372
2331static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, 2373static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
2332 u32 *rule_locs) 2374 u32 *rule_locs)
2333{ 2375{
@@ -2349,6 +2391,9 @@ static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
2349 case ETHTOOL_GRXCLSRLALL: 2391 case ETHTOOL_GRXCLSRLALL:
2350 ret = ixgbe_get_ethtool_fdir_all(adapter, cmd, rule_locs); 2392 ret = ixgbe_get_ethtool_fdir_all(adapter, cmd, rule_locs);
2351 break; 2393 break;
2394 case ETHTOOL_GRXFH:
2395 ret = ixgbe_get_rss_hash_opts(adapter, cmd);
2396 break;
2352 default: 2397 default:
2353 break; 2398 break;
2354 } 2399 }
@@ -2583,6 +2628,111 @@ static int ixgbe_del_ethtool_fdir_entry(struct ixgbe_adapter *adapter,
2583 return err; 2628 return err;
2584} 2629}
2585 2630
2631#define UDP_RSS_FLAGS (IXGBE_FLAG2_RSS_FIELD_IPV4_UDP | \
2632 IXGBE_FLAG2_RSS_FIELD_IPV6_UDP)
2633static int ixgbe_set_rss_hash_opt(struct ixgbe_adapter *adapter,
2634 struct ethtool_rxnfc *nfc)
2635{
2636 u32 flags2 = adapter->flags2;
2637
2638 /*
2639 * RSS does not support anything other than hashing
2640 * to queues on src and dst IPs and ports
2641 */
2642 if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
2643 RXH_L4_B_0_1 | RXH_L4_B_2_3))
2644 return -EINVAL;
2645
2646 switch (nfc->flow_type) {
2647 case TCP_V4_FLOW:
2648 case TCP_V6_FLOW:
2649 if (!(nfc->data & RXH_IP_SRC) ||
2650 !(nfc->data & RXH_IP_DST) ||
2651 !(nfc->data & RXH_L4_B_0_1) ||
2652 !(nfc->data & RXH_L4_B_2_3))
2653 return -EINVAL;
2654 break;
2655 case UDP_V4_FLOW:
2656 if (!(nfc->data & RXH_IP_SRC) ||
2657 !(nfc->data & RXH_IP_DST))
2658 return -EINVAL;
2659 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
2660 case 0:
2661 flags2 &= ~IXGBE_FLAG2_RSS_FIELD_IPV4_UDP;
2662 break;
2663 case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
2664 flags2 |= IXGBE_FLAG2_RSS_FIELD_IPV4_UDP;
2665 break;
2666 default:
2667 return -EINVAL;
2668 }
2669 break;
2670 case UDP_V6_FLOW:
2671 if (!(nfc->data & RXH_IP_SRC) ||
2672 !(nfc->data & RXH_IP_DST))
2673 return -EINVAL;
2674 switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
2675 case 0:
2676 flags2 &= ~IXGBE_FLAG2_RSS_FIELD_IPV6_UDP;
2677 break;
2678 case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
2679 flags2 |= IXGBE_FLAG2_RSS_FIELD_IPV6_UDP;
2680 break;
2681 default:
2682 return -EINVAL;
2683 }
2684 break;
2685 case AH_ESP_V4_FLOW:
2686 case AH_V4_FLOW:
2687 case ESP_V4_FLOW:
2688 case SCTP_V4_FLOW:
2689 case AH_ESP_V6_FLOW:
2690 case AH_V6_FLOW:
2691 case ESP_V6_FLOW:
2692 case SCTP_V6_FLOW:
2693 if (!(nfc->data & RXH_IP_SRC) ||
2694 !(nfc->data & RXH_IP_DST) ||
2695 (nfc->data & RXH_L4_B_0_1) ||
2696 (nfc->data & RXH_L4_B_2_3))
2697 return -EINVAL;
2698 break;
2699 default:
2700 return -EINVAL;
2701 }
2702
2703 /* if we changed something we need to update flags */
2704 if (flags2 != adapter->flags2) {
2705 struct ixgbe_hw *hw = &adapter->hw;
2706 u32 mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC);
2707
2708 if ((flags2 & UDP_RSS_FLAGS) &&
2709 !(adapter->flags2 & UDP_RSS_FLAGS))
2710 e_warn(drv, "enabling UDP RSS: fragmented packets"
2711 " may arrive out of order to the stack above\n");
2712
2713 adapter->flags2 = flags2;
2714
2715 /* Perform hash on these packet types */
2716 mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4
2717 | IXGBE_MRQC_RSS_FIELD_IPV4_TCP
2718 | IXGBE_MRQC_RSS_FIELD_IPV6
2719 | IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
2720
2721 mrqc &= ~(IXGBE_MRQC_RSS_FIELD_IPV4_UDP |
2722 IXGBE_MRQC_RSS_FIELD_IPV6_UDP);
2723
2724 if (flags2 & IXGBE_FLAG2_RSS_FIELD_IPV4_UDP)
2725 mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
2726
2727 if (flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP)
2728 mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
2729
2730 IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
2731 }
2732
2733 return 0;
2734}
2735
2586static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) 2736static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
2587{ 2737{
2588 struct ixgbe_adapter *adapter = netdev_priv(dev); 2738 struct ixgbe_adapter *adapter = netdev_priv(dev);
@@ -2595,6 +2745,9 @@ static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
2595 case ETHTOOL_SRXCLSRLDEL: 2745 case ETHTOOL_SRXCLSRLDEL:
2596 ret = ixgbe_del_ethtool_fdir_entry(adapter, cmd); 2746 ret = ixgbe_del_ethtool_fdir_entry(adapter, cmd);
2597 break; 2747 break;
2748 case ETHTOOL_SRXFH:
2749 ret = ixgbe_set_rss_hash_opt(adapter, cmd);
2750 break;
2598 default: 2751 default:
2599 break; 2752 break;
2600 } 2753 }
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 1d22c9f0e9fe..5c7e7d83d394 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -2856,6 +2856,11 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
2856 | IXGBE_MRQC_RSS_FIELD_IPV6 2856 | IXGBE_MRQC_RSS_FIELD_IPV6
2857 | IXGBE_MRQC_RSS_FIELD_IPV6_TCP; 2857 | IXGBE_MRQC_RSS_FIELD_IPV6_TCP;
2858 2858
2859 if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV4_UDP)
2860 mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4_UDP;
2861 if (adapter->flags2 & IXGBE_FLAG2_RSS_FIELD_IPV6_UDP)
2862 mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP;
2863
2859 IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); 2864 IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
2860} 2865}
2861 2866