diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2012-02-08 02:51:53 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2012-03-19 05:03:15 -0400 |
commit | ef6afc0caceebb3b49cd384f8c634f89f5089997 (patch) | |
tree | fd95d484357deca295bad8ab978e8a5d137590c8 /drivers/net/ethernet | |
parent | 581330ba7b219fec0587452bd72fe5635c30c4ae (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.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 153 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 5 |
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 | ||
2331 | static 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 | |||
2331 | static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, | 2373 | static 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) | ||
2633 | static 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 | |||
2586 | static int ixgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) | 2736 | static 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 | ||