Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b240a0e5 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller
Browse files

ethtool: Add GGRO and SGRO ops



This patch adds the ethtool ops to enable and disable GRO.  It also
makes GRO depend on RX checksum offload much the same as how TSO
depends on SG support.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bf296b12
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -467,6 +467,8 @@ struct ethtool_ops {


#define	ETHTOOL_GRXFH		0x00000029 /* Get RX flow hash configuration */
#define	ETHTOOL_GRXFH		0x00000029 /* Get RX flow hash configuration */
#define	ETHTOOL_SRXFH		0x0000002a /* Set RX flow hash configuration */
#define	ETHTOOL_SRXFH		0x0000002a /* Set RX flow hash configuration */
#define ETHTOOL_GGRO		0x0000002b /* Get GRO enable (ethtool_value) */
#define ETHTOOL_SGRO		0x0000002c /* Set GRO enable (ethtool_value) */


/* compatibility with older code */
/* compatibility with older code */
#define SPARC_ETH_GSET		ETHTOOL_GSET
#define SPARC_ETH_GSET		ETHTOOL_GSET
+51 −2
Original line number Original line Diff line number Diff line
@@ -528,6 +528,22 @@ static int ethtool_set_tx_csum(struct net_device *dev, char __user *useraddr)
	return dev->ethtool_ops->set_tx_csum(dev, edata.data);
	return dev->ethtool_ops->set_tx_csum(dev, edata.data);
}
}


static int ethtool_set_rx_csum(struct net_device *dev, char __user *useraddr)
{
	struct ethtool_value edata;

	if (!dev->ethtool_ops->set_rx_csum)
		return -EOPNOTSUPP;

	if (copy_from_user(&edata, useraddr, sizeof(edata)))
		return -EFAULT;

	if (!edata.data && dev->ethtool_ops->set_sg)
		dev->features &= ~NETIF_F_GRO;

	return dev->ethtool_ops->set_rx_csum(dev, edata.data);
}

static int ethtool_set_sg(struct net_device *dev, char __user *useraddr)
static int ethtool_set_sg(struct net_device *dev, char __user *useraddr)
{
{
	struct ethtool_value edata;
	struct ethtool_value edata;
@@ -599,6 +615,34 @@ static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
	return 0;
	return 0;
}
}


static int ethtool_get_gro(struct net_device *dev, char __user *useraddr)
{
	struct ethtool_value edata = { ETHTOOL_GGRO };

	edata.data = dev->features & NETIF_F_GRO;
	if (copy_to_user(useraddr, &edata, sizeof(edata)))
		 return -EFAULT;
	return 0;
}

static int ethtool_set_gro(struct net_device *dev, char __user *useraddr)
{
	struct ethtool_value edata;

	if (copy_from_user(&edata, useraddr, sizeof(edata)))
		return -EFAULT;

	if (edata.data) {
		if (!dev->ethtool_ops->get_rx_csum ||
		    !dev->ethtool_ops->get_rx_csum(dev))
			return -EINVAL;
		dev->features |= NETIF_F_GRO;
	} else
		dev->features &= ~NETIF_F_GRO;

	return 0;
}

static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
{
{
	struct ethtool_test test;
	struct ethtool_test test;
@@ -932,8 +976,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
				       dev->ethtool_ops->get_rx_csum);
				       dev->ethtool_ops->get_rx_csum);
		break;
		break;
	case ETHTOOL_SRXCSUM:
	case ETHTOOL_SRXCSUM:
		rc = ethtool_set_value(dev, useraddr,
		rc = ethtool_set_rx_csum(dev, useraddr);
				       dev->ethtool_ops->set_rx_csum);
		break;
		break;
	case ETHTOOL_GTXCSUM:
	case ETHTOOL_GTXCSUM:
		rc = ethtool_get_value(dev, useraddr, ethcmd,
		rc = ethtool_get_value(dev, useraddr, ethcmd,
@@ -1014,6 +1057,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
	case ETHTOOL_SRXFH:
	case ETHTOOL_SRXFH:
		rc = ethtool_set_rxhash(dev, useraddr);
		rc = ethtool_set_rxhash(dev, useraddr);
		break;
		break;
	case ETHTOOL_GGRO:
		rc = ethtool_get_gro(dev, useraddr);
		break;
	case ETHTOOL_SGRO:
		rc = ethtool_set_gro(dev, useraddr);
		break;
	default:
	default:
		rc = -EOPNOTSUPP;
		rc = -EOPNOTSUPP;
	}
	}