Signed-off-by: Auke Kok <[EMAIL PROTECTED]> --- include/linux/ethtool.h | 8 +++++++ include/linux/netdevice.h | 1 + net/core/ethtool.c | 54 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 1 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 3a63224..ab9d688 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -274,6 +274,8 @@ int ethtool_op_get_perm_addr(struct net_device *dev, struct ethtool_perm_addr *addr, u8 *data); u32 ethtool_op_get_ufo(struct net_device *dev); int ethtool_op_set_ufo(struct net_device *dev, u32 data); +u32 ethtool_op_get_lro(struct net_device *dev); +int ethtool_op_set_lro(struct net_device *dev, u32 data); /** * ðtool_ops - Alter and report network device settings @@ -305,6 +307,8 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data); * set_tso: Turn TCP segmentation offload on or off * get_ufo: Report whether UDP fragmentation offload is enabled * set_ufo: Turn UDP fragmentation offload on or off + * get_lro: Report whether large receive offload is enabled + * set_lro: Turn large receive offload on or off * self_test: Run specified self-tests * get_strings: Return a set of strings that describe the requested objects * phys_id: Identify the device @@ -373,6 +377,8 @@ struct ethtool_ops { void (*complete)(struct net_device *); u32 (*get_ufo)(struct net_device *); int (*set_ufo)(struct net_device *, u32); + u32 (*get_lro)(struct net_device *); + int (*set_lro)(struct net_device *, u32); }; #endif /* __KERNEL__ */ @@ -414,6 +420,8 @@ struct ethtool_ops { #define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */ #define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */ #define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */ +#define ETHTOOL_GLRO 0x00000025 /* Get LRO enable (ethtool_value) */ +#define ETHTOOL_SLRO 0x00000026 /* Set LRO enable (ethtool_value) */ /* compatibility with older code */ #define SPARC_ETH_GSET ETHTOOL_GSET diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 4a616d7..4863ffc 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -341,6 +341,7 @@ struct net_device #define NETIF_F_GSO 2048 /* Enable software GSO. */ #define NETIF_F_LLTX 4096 /* LockLess TX */ #define NETIF_F_MULTI_QUEUE 16384 /* Has multiple TX/RX queues */ +#define NETIF_F_LRO 32768 /* Has large receive offload */ /* Segmentation offload features */ #define NETIF_F_GSO_SHIFT 16 diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 0b531e9..23ccaa1 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -104,7 +104,6 @@ int ethtool_op_get_perm_addr(struct net_device *dev, struct ethtool_perm_addr *a return 0; } - u32 ethtool_op_get_ufo(struct net_device *dev) { return (dev->features & NETIF_F_UFO) != 0; @@ -119,6 +118,20 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data) return 0; } +u32 ethtool_op_get_lro(struct net_device *dev) +{ + return (dev->features & NETIF_F_LRO) != 0; +} + +int ethtool_op_set_lro(struct net_device *dev, u32 data) +{ + if (data) + dev->features |= NETIF_F_LRO; + else + dev->features &= ~NETIF_F_LRO; + return 0; +} + /* Handlers for each ethtool command */ static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) @@ -514,6 +527,13 @@ static int __ethtool_set_sg(struct net_device *dev, u32 data) if (err) return err; } + + if (!data && dev->ethtool_ops->set_lro) { + err = dev->ethtool_ops->set_lro(dev, 0); + if (err) + return err; + } + return dev->ethtool_ops->set_sg(dev, data); } @@ -625,6 +645,29 @@ static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr) return dev->ethtool_ops->set_ufo(dev, edata.data); } +static int ethtool_get_lro(struct net_device *dev, char __user *useraddr) +{ + struct ethtool_value edata = { ETHTOOL_GLRO }; + + edata.data = dev->features & NETIF_F_LRO; + if (copy_to_user(useraddr, &edata, sizeof(edata))) + return -EFAULT; + return 0; +} + +static int ethtool_set_lro(struct net_device *dev, char __user *useraddr) +{ + struct ethtool_value edata; + + if (copy_from_user(&edata, useraddr, sizeof(edata))) + return -EFAULT; + if (edata.data) + dev->features |= NETIF_F_LRO; + else + dev->features &= ~NETIF_F_LRO; + return 0; +} + static int ethtool_get_gso(struct net_device *dev, char __user *useraddr) { struct ethtool_value edata = { ETHTOOL_GGSO }; @@ -840,6 +883,7 @@ int dev_ethtool(struct ifreq *ifr) case ETHTOOL_GTSO: case ETHTOOL_GPERMADDR: case ETHTOOL_GUFO: + case ETHTOOL_GLRO: case ETHTOOL_GGSO: break; default: @@ -953,6 +997,12 @@ int dev_ethtool(struct ifreq *ifr) case ETHTOOL_SUFO: rc = ethtool_set_ufo(dev, useraddr); break; + case ETHTOOL_GLRO: + rc = ethtool_get_lro(dev, useraddr); + break; + case ETHTOOL_SLRO: + rc = ethtool_set_lro(dev, useraddr); + break; case ETHTOOL_GGSO: rc = ethtool_get_gso(dev, useraddr); break; @@ -994,3 +1044,5 @@ EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum); EXPORT_SYMBOL(ethtool_op_set_ufo); EXPORT_SYMBOL(ethtool_op_get_ufo); +EXPORT_SYMBOL(ethtool_op_set_lro); +EXPORT_SYMBOL(ethtool_op_get_lro); - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html