mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
net: Implement SFEATURES compatibility for not updated drivers
Use discrete setting ops for not updated drivers. This will not make them conform to full G/SFEATURES semantics, though. Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4e4db20054
commit
39fc0ce571
2 changed files with 66 additions and 0 deletions
|
@ -591,6 +591,9 @@ struct ethtool_sfeatures {
|
||||||
* Probably there are other device-specific constraints on some features
|
* Probably there are other device-specific constraints on some features
|
||||||
* in the set. When %ETHTOOL_F_UNSUPPORTED is set, .valid is considered
|
* in the set. When %ETHTOOL_F_UNSUPPORTED is set, .valid is considered
|
||||||
* here as though ignored bits were cleared.
|
* here as though ignored bits were cleared.
|
||||||
|
* %ETHTOOL_F_COMPAT - some or all changes requested were made by calling
|
||||||
|
* compatibility functions. Requested offload state cannot be properly
|
||||||
|
* managed by kernel.
|
||||||
*
|
*
|
||||||
* Meaning of bits in the masks are obtained by %ETHTOOL_GSSET_INFO (number of
|
* Meaning of bits in the masks are obtained by %ETHTOOL_GSSET_INFO (number of
|
||||||
* bits in the arrays - always multiple of 32) and %ETHTOOL_GSTRINGS commands
|
* bits in the arrays - always multiple of 32) and %ETHTOOL_GSTRINGS commands
|
||||||
|
@ -600,10 +603,12 @@ struct ethtool_sfeatures {
|
||||||
enum ethtool_sfeatures_retval_bits {
|
enum ethtool_sfeatures_retval_bits {
|
||||||
ETHTOOL_F_UNSUPPORTED__BIT,
|
ETHTOOL_F_UNSUPPORTED__BIT,
|
||||||
ETHTOOL_F_WISH__BIT,
|
ETHTOOL_F_WISH__BIT,
|
||||||
|
ETHTOOL_F_COMPAT__BIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ETHTOOL_F_UNSUPPORTED (1 << ETHTOOL_F_UNSUPPORTED__BIT)
|
#define ETHTOOL_F_UNSUPPORTED (1 << ETHTOOL_F_UNSUPPORTED__BIT)
|
||||||
#define ETHTOOL_F_WISH (1 << ETHTOOL_F_WISH__BIT)
|
#define ETHTOOL_F_WISH (1 << ETHTOOL_F_WISH__BIT)
|
||||||
|
#define ETHTOOL_F_COMPAT (1 << ETHTOOL_F_COMPAT__BIT)
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,64 @@ static void ethtool_get_features_compat(struct net_device *dev,
|
||||||
if (dev->ethtool_ops->get_rx_csum)
|
if (dev->ethtool_ops->get_rx_csum)
|
||||||
if (dev->ethtool_ops->get_rx_csum(dev))
|
if (dev->ethtool_ops->get_rx_csum(dev))
|
||||||
features[0].active |= NETIF_F_RXCSUM;
|
features[0].active |= NETIF_F_RXCSUM;
|
||||||
|
|
||||||
|
/* mark legacy-changeable features */
|
||||||
|
if (dev->ethtool_ops->set_sg)
|
||||||
|
features[0].available |= NETIF_F_SG;
|
||||||
|
if (dev->ethtool_ops->set_tx_csum)
|
||||||
|
features[0].available |= NETIF_F_ALL_CSUM;
|
||||||
|
if (dev->ethtool_ops->set_tso)
|
||||||
|
features[0].available |= NETIF_F_ALL_TSO;
|
||||||
|
if (dev->ethtool_ops->set_rx_csum)
|
||||||
|
features[0].available |= NETIF_F_RXCSUM;
|
||||||
|
if (dev->ethtool_ops->set_flags)
|
||||||
|
features[0].available |= flags_dup_features;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ethtool_set_feature_compat(struct net_device *dev,
|
||||||
|
int (*legacy_set)(struct net_device *, u32),
|
||||||
|
struct ethtool_set_features_block *features, u32 mask)
|
||||||
|
{
|
||||||
|
u32 do_set;
|
||||||
|
|
||||||
|
if (!legacy_set)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(features[0].valid & mask))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
features[0].valid &= ~mask;
|
||||||
|
|
||||||
|
do_set = !!(features[0].requested & mask);
|
||||||
|
|
||||||
|
if (legacy_set(dev, do_set) < 0)
|
||||||
|
netdev_info(dev,
|
||||||
|
"Legacy feature change (%s) failed for 0x%08x\n",
|
||||||
|
do_set ? "set" : "clear", mask);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ethtool_set_features_compat(struct net_device *dev,
|
||||||
|
struct ethtool_set_features_block *features)
|
||||||
|
{
|
||||||
|
int compat;
|
||||||
|
|
||||||
|
if (!dev->ethtool_ops)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
compat = ethtool_set_feature_compat(dev, dev->ethtool_ops->set_sg,
|
||||||
|
features, NETIF_F_SG);
|
||||||
|
compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_tx_csum,
|
||||||
|
features, NETIF_F_ALL_CSUM);
|
||||||
|
compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_tso,
|
||||||
|
features, NETIF_F_ALL_TSO);
|
||||||
|
compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_rx_csum,
|
||||||
|
features, NETIF_F_RXCSUM);
|
||||||
|
compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_flags,
|
||||||
|
features, flags_dup_features);
|
||||||
|
|
||||||
|
return compat;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
|
static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
|
||||||
|
@ -234,6 +292,9 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
|
||||||
if (features[0].valid & ~NETIF_F_ETHTOOL_BITS)
|
if (features[0].valid & ~NETIF_F_ETHTOOL_BITS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (ethtool_set_features_compat(dev, features))
|
||||||
|
ret |= ETHTOOL_F_COMPAT;
|
||||||
|
|
||||||
if (features[0].valid & ~dev->hw_features) {
|
if (features[0].valid & ~dev->hw_features) {
|
||||||
features[0].valid &= dev->hw_features;
|
features[0].valid &= dev->hw_features;
|
||||||
ret |= ETHTOOL_F_UNSUPPORTED;
|
ret |= ETHTOOL_F_UNSUPPORTED;
|
||||||
|
|
Loading…
Reference in a new issue