diff options
-rw-r--r-- | drivers/net/ixgbe/ixgbe_82599.c | 57 | ||||
-rw-r--r-- | include/linux/ethtool.h | 5 | ||||
-rw-r--r-- | net/core/ethtool.c | 34 |
3 files changed, 51 insertions, 45 deletions
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 3e06a61da921..e80657c75506 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c | |||
@@ -1910,56 +1910,27 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, | |||
1910 | (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT))); | 1910 | (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT))); |
1911 | 1911 | ||
1912 | /* | 1912 | /* |
1913 | * Program the relevant mask registers. If src/dst_port or src/dst_addr | 1913 | * Program the relevant mask registers. L4type cannot be |
1914 | * are zero, then assume a full mask for that field. Also assume that | 1914 | * masked out in this implementation. |
1915 | * a VLAN of 0 is unspecified, so mask that out as well. L4type | ||
1916 | * cannot be masked out in this implementation. | ||
1917 | * | 1915 | * |
1918 | * This also assumes IPv4 only. IPv6 masking isn't supported at this | 1916 | * This also assumes IPv4 only. IPv6 masking isn't supported at this |
1919 | * point in time. | 1917 | * point in time. |
1920 | */ | 1918 | */ |
1921 | if (src_ipv4 == 0) | 1919 | IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask); |
1922 | IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, 0xffffffff); | 1920 | IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask); |
1923 | else | ||
1924 | IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask); | ||
1925 | |||
1926 | if (dst_ipv4 == 0) | ||
1927 | IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, 0xffffffff); | ||
1928 | else | ||
1929 | IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask); | ||
1930 | 1921 | ||
1931 | switch (l4type & IXGBE_ATR_L4TYPE_MASK) { | 1922 | switch (l4type & IXGBE_ATR_L4TYPE_MASK) { |
1932 | case IXGBE_ATR_L4TYPE_TCP: | 1923 | case IXGBE_ATR_L4TYPE_TCP: |
1933 | if (src_port == 0) | 1924 | IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, input_masks->src_port_mask); |
1934 | IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xffff); | 1925 | IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, |
1935 | else | 1926 | (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) | |
1936 | IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, | 1927 | (input_masks->dst_port_mask << 16))); |
1937 | input_masks->src_port_mask); | ||
1938 | |||
1939 | if (dst_port == 0) | ||
1940 | IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, | ||
1941 | (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) | | ||
1942 | (0xffff << 16))); | ||
1943 | else | ||
1944 | IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, | ||
1945 | (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) | | ||
1946 | (input_masks->dst_port_mask << 16))); | ||
1947 | break; | 1928 | break; |
1948 | case IXGBE_ATR_L4TYPE_UDP: | 1929 | case IXGBE_ATR_L4TYPE_UDP: |
1949 | if (src_port == 0) | 1930 | IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, input_masks->src_port_mask); |
1950 | IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xffff); | 1931 | IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, |
1951 | else | 1932 | (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) | |
1952 | IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, | 1933 | (input_masks->src_port_mask << 16))); |
1953 | input_masks->src_port_mask); | ||
1954 | |||
1955 | if (dst_port == 0) | ||
1956 | IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, | ||
1957 | (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) | | ||
1958 | (0xffff << 16))); | ||
1959 | else | ||
1960 | IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, | ||
1961 | (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) | | ||
1962 | (input_masks->src_port_mask << 16))); | ||
1963 | break; | 1934 | break; |
1964 | default: | 1935 | default: |
1965 | /* this already would have failed above */ | 1936 | /* this already would have failed above */ |
@@ -1967,11 +1938,11 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw, | |||
1967 | } | 1938 | } |
1968 | 1939 | ||
1969 | /* Program the last mask register, FDIRM */ | 1940 | /* Program the last mask register, FDIRM */ |
1970 | if (input_masks->vlan_id_mask || !vlan_id) | 1941 | if (input_masks->vlan_id_mask) |
1971 | /* Mask both VLAN and VLANP - bits 0 and 1 */ | 1942 | /* Mask both VLAN and VLANP - bits 0 and 1 */ |
1972 | fdirm |= 0x3; | 1943 | fdirm |= 0x3; |
1973 | 1944 | ||
1974 | if (input_masks->data_mask || !flex_bytes) | 1945 | if (input_masks->data_mask) |
1975 | /* Flex bytes need masking, so mask the whole thing - bit 4 */ | 1946 | /* Flex bytes need masking, so mask the whole thing - bit 4 */ |
1976 | fdirm |= 0x10; | 1947 | fdirm |= 0x10; |
1977 | 1948 | ||
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index d64e246a39e7..00334eebbe26 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h | |||
@@ -470,8 +470,9 @@ struct ethtool_rxfh_indir { | |||
470 | * @action: RX ring/queue index to deliver to (non-negative) or other action | 470 | * @action: RX ring/queue index to deliver to (non-negative) or other action |
471 | * (negative, e.g. %ETHTOOL_RXNTUPLE_ACTION_DROP) | 471 | * (negative, e.g. %ETHTOOL_RXNTUPLE_ACTION_DROP) |
472 | * | 472 | * |
473 | * Zero values in @h_u may be ignored, as if all the corresponding | 473 | * For flow types %TCP_V4_FLOW, %UDP_V4_FLOW and %SCTP_V4_FLOW, where |
474 | * mask bits were set. | 474 | * a field value and mask are both zero this is treated as if all mask |
475 | * bits are set i.e. the field is ignored. | ||
475 | */ | 476 | */ |
476 | struct ethtool_rx_ntuple_flow_spec { | 477 | struct ethtool_rx_ntuple_flow_spec { |
477 | __u32 flow_type; | 478 | __u32 flow_type; |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 248c25c3e820..91ffce20c36b 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -485,6 +485,38 @@ static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, | |||
485 | list->count++; | 485 | list->count++; |
486 | } | 486 | } |
487 | 487 | ||
488 | /* | ||
489 | * ethtool does not (or did not) set masks for flow parameters that are | ||
490 | * not specified, so if both value and mask are 0 then this must be | ||
491 | * treated as equivalent to a mask with all bits set. Implement that | ||
492 | * here rather than in drivers. | ||
493 | */ | ||
494 | static void rx_ntuple_fix_masks(struct ethtool_rx_ntuple_flow_spec *fs) | ||
495 | { | ||
496 | struct ethtool_tcpip4_spec *entry = &fs->h_u.tcp_ip4_spec; | ||
497 | struct ethtool_tcpip4_spec *mask = &fs->m_u.tcp_ip4_spec; | ||
498 | |||
499 | if (fs->flow_type != TCP_V4_FLOW && | ||
500 | fs->flow_type != UDP_V4_FLOW && | ||
501 | fs->flow_type != SCTP_V4_FLOW) | ||
502 | return; | ||
503 | |||
504 | if (!(entry->ip4src | mask->ip4src)) | ||
505 | mask->ip4src = htonl(0xffffffff); | ||
506 | if (!(entry->ip4dst | mask->ip4dst)) | ||
507 | mask->ip4dst = htonl(0xffffffff); | ||
508 | if (!(entry->psrc | mask->psrc)) | ||
509 | mask->psrc = htons(0xffff); | ||
510 | if (!(entry->pdst | mask->pdst)) | ||
511 | mask->pdst = htons(0xffff); | ||
512 | if (!(entry->tos | mask->tos)) | ||
513 | mask->tos = 0xff; | ||
514 | if (!(fs->vlan_tag | fs->vlan_tag_mask)) | ||
515 | fs->vlan_tag_mask = 0xffff; | ||
516 | if (!(fs->data | fs->data_mask)) | ||
517 | fs->data_mask = 0xffffffffffffffffULL; | ||
518 | } | ||
519 | |||
488 | static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev, | 520 | static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev, |
489 | void __user *useraddr) | 521 | void __user *useraddr) |
490 | { | 522 | { |
@@ -499,6 +531,8 @@ static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev, | |||
499 | if (copy_from_user(&cmd, useraddr, sizeof(cmd))) | 531 | if (copy_from_user(&cmd, useraddr, sizeof(cmd))) |
500 | return -EFAULT; | 532 | return -EFAULT; |
501 | 533 | ||
534 | rx_ntuple_fix_masks(&cmd.fs); | ||
535 | |||
502 | /* | 536 | /* |
503 | * Cache filter in dev struct for GET operation only if | 537 | * Cache filter in dev struct for GET operation only if |
504 | * the underlying driver doesn't have its own GET operation, and | 538 | * the underlying driver doesn't have its own GET operation, and |