Loading net/core/ethtool.c +32 −13 Original line number Original line Diff line number Diff line Loading @@ -357,15 +357,21 @@ static void *__ethtool_get_one_feature_actor(struct net_device *dev, u32 ethcmd) static int ethtool_get_one_feature(struct net_device *dev, static int ethtool_get_one_feature(struct net_device *dev, char __user *useraddr, u32 ethcmd) char __user *useraddr, u32 ethcmd) { { u32 mask = ethtool_get_feature_mask(ethcmd); struct ethtool_value edata = { struct ethtool_value edata = { .cmd = ethcmd, .cmd = ethcmd, .data = !!(dev->features & ethtool_get_feature_mask(ethcmd)), .data = !!(dev->features & mask), }; }; /* compatibility with discrete get_ ops */ if (!(dev->hw_features & mask)) { u32 (*actor)(struct net_device *); u32 (*actor)(struct net_device *); actor = __ethtool_get_one_feature_actor(dev, ethcmd); actor = __ethtool_get_one_feature_actor(dev, ethcmd); if (actor) if (actor) edata.data = actor(dev); edata.data = actor(dev); } if (copy_to_user(useraddr, &edata, sizeof(edata))) if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return -EFAULT; Loading @@ -386,6 +392,27 @@ static int ethtool_set_one_feature(struct net_device *dev, if (copy_from_user(&edata, useraddr, sizeof(edata))) if (copy_from_user(&edata, useraddr, sizeof(edata))) return -EFAULT; return -EFAULT; mask = ethtool_get_feature_mask(ethcmd); mask &= dev->hw_features; if (mask) { if (edata.data) dev->wanted_features |= mask; else dev->wanted_features &= ~mask; netdev_update_features(dev); return 0; } /* Driver is not converted to ndo_fix_features or does not * support changing this offload. In the latter case it won't * have corresponding ethtool_ops field set. * * Following part is to be removed after all drivers advertise * their changeable features in netdev->hw_features and stop * using discrete offload setting ops. */ switch (ethcmd) { switch (ethcmd) { case ETHTOOL_STXCSUM: case ETHTOOL_STXCSUM: return __ethtool_set_tx_csum(dev, edata.data); return __ethtool_set_tx_csum(dev, edata.data); Loading @@ -395,14 +422,6 @@ static int ethtool_set_one_feature(struct net_device *dev, return __ethtool_set_tso(dev, edata.data); return __ethtool_set_tso(dev, edata.data); case ETHTOOL_SUFO: case ETHTOOL_SUFO: return __ethtool_set_ufo(dev, edata.data); return __ethtool_set_ufo(dev, edata.data); case ETHTOOL_SGSO: case ETHTOOL_SGRO: mask = ethtool_get_feature_mask(ethcmd); if (edata.data) dev->features |= mask; else dev->features &= ~mask; return 0; default: default: return -EOPNOTSUPP; return -EOPNOTSUPP; } } Loading Loading
net/core/ethtool.c +32 −13 Original line number Original line Diff line number Diff line Loading @@ -357,15 +357,21 @@ static void *__ethtool_get_one_feature_actor(struct net_device *dev, u32 ethcmd) static int ethtool_get_one_feature(struct net_device *dev, static int ethtool_get_one_feature(struct net_device *dev, char __user *useraddr, u32 ethcmd) char __user *useraddr, u32 ethcmd) { { u32 mask = ethtool_get_feature_mask(ethcmd); struct ethtool_value edata = { struct ethtool_value edata = { .cmd = ethcmd, .cmd = ethcmd, .data = !!(dev->features & ethtool_get_feature_mask(ethcmd)), .data = !!(dev->features & mask), }; }; /* compatibility with discrete get_ ops */ if (!(dev->hw_features & mask)) { u32 (*actor)(struct net_device *); u32 (*actor)(struct net_device *); actor = __ethtool_get_one_feature_actor(dev, ethcmd); actor = __ethtool_get_one_feature_actor(dev, ethcmd); if (actor) if (actor) edata.data = actor(dev); edata.data = actor(dev); } if (copy_to_user(useraddr, &edata, sizeof(edata))) if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return -EFAULT; Loading @@ -386,6 +392,27 @@ static int ethtool_set_one_feature(struct net_device *dev, if (copy_from_user(&edata, useraddr, sizeof(edata))) if (copy_from_user(&edata, useraddr, sizeof(edata))) return -EFAULT; return -EFAULT; mask = ethtool_get_feature_mask(ethcmd); mask &= dev->hw_features; if (mask) { if (edata.data) dev->wanted_features |= mask; else dev->wanted_features &= ~mask; netdev_update_features(dev); return 0; } /* Driver is not converted to ndo_fix_features or does not * support changing this offload. In the latter case it won't * have corresponding ethtool_ops field set. * * Following part is to be removed after all drivers advertise * their changeable features in netdev->hw_features and stop * using discrete offload setting ops. */ switch (ethcmd) { switch (ethcmd) { case ETHTOOL_STXCSUM: case ETHTOOL_STXCSUM: return __ethtool_set_tx_csum(dev, edata.data); return __ethtool_set_tx_csum(dev, edata.data); Loading @@ -395,14 +422,6 @@ static int ethtool_set_one_feature(struct net_device *dev, return __ethtool_set_tso(dev, edata.data); return __ethtool_set_tso(dev, edata.data); case ETHTOOL_SUFO: case ETHTOOL_SUFO: return __ethtool_set_ufo(dev, edata.data); return __ethtool_set_ufo(dev, edata.data); case ETHTOOL_SGSO: case ETHTOOL_SGRO: mask = ethtool_get_feature_mask(ethcmd); if (edata.data) dev->features |= mask; else dev->features &= ~mask; return 0; default: default: return -EOPNOTSUPP; return -EOPNOTSUPP; } } Loading