Commit 55664f32 authored by Ben Hutchings's avatar Ben Hutchings Committed by David S. Miller

ethtool: Allow drivers to select RX NFC rule locations

Define special location values for RX NFC that request the driver to
select the actual rule location.  This allows for implementation on
devices that use hash-based filter lookup, whereas currently the API is
more suited to devices with TCAM lookup or linear search.

In ethtool_set_rxnfc() and the compat wrapper ethtool_ioctl(), copy
the structure back to user-space after insertion so that the actual
location is returned.
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3a73e49c
...@@ -489,7 +489,10 @@ struct ethtool_rx_flow_spec { ...@@ -489,7 +489,10 @@ struct ethtool_rx_flow_spec {
* on return. * on return.
* *
* For %ETHTOOL_GRXCLSRLCNT, @rule_cnt is set to the number of defined * For %ETHTOOL_GRXCLSRLCNT, @rule_cnt is set to the number of defined
* rules on return. * rules on return. If @data is non-zero on return then it is the
* size of the rule table, plus the flag %RX_CLS_LOC_SPECIAL if the
* driver supports any special location values. If that flag is not
* set in @data then special location values should not be used.
* *
* For %ETHTOOL_GRXCLSRULE, @fs.@location specifies the location of an * For %ETHTOOL_GRXCLSRULE, @fs.@location specifies the location of an
* existing rule on entry and @fs contains the rule on return. * existing rule on entry and @fs contains the rule on return.
...@@ -501,10 +504,23 @@ struct ethtool_rx_flow_spec { ...@@ -501,10 +504,23 @@ struct ethtool_rx_flow_spec {
* must use the second parameter to get_rxnfc() instead of @rule_locs. * must use the second parameter to get_rxnfc() instead of @rule_locs.
* *
* For %ETHTOOL_SRXCLSRLINS, @fs specifies the rule to add or update. * For %ETHTOOL_SRXCLSRLINS, @fs specifies the rule to add or update.
* @fs.@location specifies the location to use and must not be ignored. * @fs.@location either specifies the location to use or is a special
* location value with %RX_CLS_LOC_SPECIAL flag set. On return,
* @fs.@location is the actual rule location.
* *
* For %ETHTOOL_SRXCLSRLDEL, @fs.@location specifies the location of an * For %ETHTOOL_SRXCLSRLDEL, @fs.@location specifies the location of an
* existing rule on entry. * existing rule on entry.
*
* A driver supporting the special location values for
* %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;
* %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
* defined in future and drivers must return -%EINVAL for any
* unrecognised value.
*/ */
struct ethtool_rxnfc { struct ethtool_rxnfc {
__u32 cmd; __u32 cmd;
...@@ -1141,6 +1157,12 @@ struct ethtool_ops { ...@@ -1141,6 +1157,12 @@ struct ethtool_ops {
#define RX_CLS_FLOW_DISC 0xffffffffffffffffULL #define RX_CLS_FLOW_DISC 0xffffffffffffffffULL
/* Special RX classification rule insert location values */
#define RX_CLS_LOC_SPECIAL 0x80000000 /* flag */
#define RX_CLS_LOC_ANY 0xffffffff
#define RX_CLS_LOC_FIRST 0xfffffffe
#define RX_CLS_LOC_LAST 0xfffffffd
/* Reset flags */ /* Reset flags */
/* The reset() operation must clear the flags for the components which /* The reset() operation must clear the flags for the components which
* were actually reset. On successful return, the flags indicate the * were actually reset. On successful return, the flags indicate the
......
...@@ -439,6 +439,7 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, ...@@ -439,6 +439,7 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
{ {
struct ethtool_rxnfc info; struct ethtool_rxnfc info;
size_t info_size = sizeof(info); size_t info_size = sizeof(info);
int rc;
if (!dev->ethtool_ops->set_rxnfc) if (!dev->ethtool_ops->set_rxnfc)
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -454,7 +455,15 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, ...@@ -454,7 +455,15 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
if (copy_from_user(&info, useraddr, info_size)) if (copy_from_user(&info, useraddr, info_size))
return -EFAULT; return -EFAULT;
return dev->ethtool_ops->set_rxnfc(dev, &info); rc = dev->ethtool_ops->set_rxnfc(dev, &info);
if (rc)
return rc;
if (cmd == ETHTOOL_SRXCLSRLINS &&
copy_to_user(useraddr, &info, info_size))
return -EFAULT;
return 0;
} }
static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
......
...@@ -2758,10 +2758,10 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) ...@@ -2758,10 +2758,10 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
case ETHTOOL_GRXRINGS: case ETHTOOL_GRXRINGS:
case ETHTOOL_GRXCLSRLCNT: case ETHTOOL_GRXCLSRLCNT:
case ETHTOOL_GRXCLSRULE: case ETHTOOL_GRXCLSRULE:
case ETHTOOL_SRXCLSRLINS:
convert_out = true; convert_out = true;
/* fall through */ /* fall through */
case ETHTOOL_SRXCLSRLDEL: case ETHTOOL_SRXCLSRLDEL:
case ETHTOOL_SRXCLSRLINS:
buf_size += sizeof(struct ethtool_rxnfc); buf_size += sizeof(struct ethtool_rxnfc);
convert_in = true; convert_in = true;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment