diff options
Diffstat (limited to 'drivers/net/xen-netfront.c')
| -rw-r--r-- | drivers/net/xen-netfront.c | 106 | 
1 files changed, 51 insertions, 55 deletions
| diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 5c8d9c385be0..db9a763aaa7f 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1140,6 +1140,42 @@ static void xennet_uninit(struct net_device *dev)  	gnttab_free_grant_references(np->gref_rx_head);  } +static u32 xennet_fix_features(struct net_device *dev, u32 features) +{ +	struct netfront_info *np = netdev_priv(dev); +	int val; + +	if (features & NETIF_F_SG) { +		if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-sg", +				 "%d", &val) < 0) +			val = 0; + +		if (!val) +			features &= ~NETIF_F_SG; +	} + +	if (features & NETIF_F_TSO) { +		if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, +				 "feature-gso-tcpv4", "%d", &val) < 0) +			val = 0; + +		if (!val) +			features &= ~NETIF_F_TSO; +	} + +	return features; +} + +static int xennet_set_features(struct net_device *dev, u32 features) +{ +	if (!(features & NETIF_F_SG) && dev->mtu > ETH_DATA_LEN) { +		netdev_info(dev, "Reducing MTU because no SG offload"); +		dev->mtu = ETH_DATA_LEN; +	} + +	return 0; +} +  static const struct net_device_ops xennet_netdev_ops = {  	.ndo_open            = xennet_open,  	.ndo_uninit          = xennet_uninit, @@ -1148,6 +1184,8 @@ static const struct net_device_ops xennet_netdev_ops = {  	.ndo_change_mtu	     = xennet_change_mtu,  	.ndo_set_mac_address = eth_mac_addr,  	.ndo_validate_addr   = eth_validate_addr, +	.ndo_fix_features    = xennet_fix_features, +	.ndo_set_features    = xennet_set_features,  };  static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev) @@ -1209,7 +1247,17 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev  	netdev->netdev_ops	= &xennet_netdev_ops;  	netif_napi_add(netdev, &np->napi, xennet_poll, 64); -	netdev->features        = NETIF_F_IP_CSUM; +	netdev->features        = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | +				  NETIF_F_GSO_ROBUST; +	netdev->hw_features	= NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO; + +	/* +         * Assume that all hw features are available for now. This set +         * will be adjusted by the call to netdev_update_features() in +         * xennet_connect() which is the earliest point where we can +         * negotiate with the backend regarding supported features. +         */ +	netdev->features |= netdev->hw_features;  	SET_ETHTOOL_OPS(netdev, &xennet_ethtool_ops);  	SET_NETDEV_DEV(netdev, &dev->dev); @@ -1416,8 +1464,7 @@ static int setup_netfront(struct xenbus_device *dev, struct netfront_info *info)  		goto fail;  	err = bind_evtchn_to_irqhandler(info->evtchn, xennet_interrupt, -					IRQF_SAMPLE_RANDOM, netdev->name, -					netdev); +					0, netdev->name, netdev);  	if (err < 0)  		goto fail;  	netdev->irq = err; @@ -1510,54 +1557,6 @@ again:  	return err;  } -static int xennet_set_sg(struct net_device *dev, u32 data) -{ -	if (data) { -		struct netfront_info *np = netdev_priv(dev); -		int val; - -		if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-sg", -				 "%d", &val) < 0) -			val = 0; -		if (!val) -			return -ENOSYS; -	} else if (dev->mtu > ETH_DATA_LEN) -		dev->mtu = ETH_DATA_LEN; - -	return ethtool_op_set_sg(dev, data); -} - -static int xennet_set_tso(struct net_device *dev, u32 data) -{ -	if (data) { -		struct netfront_info *np = netdev_priv(dev); -		int val; - -		if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, -				 "feature-gso-tcpv4", "%d", &val) < 0) -			val = 0; -		if (!val) -			return -ENOSYS; -	} - -	return ethtool_op_set_tso(dev, data); -} - -static void xennet_set_features(struct net_device *dev) -{ -	/* Turn off all GSO bits except ROBUST. */ -	dev->features &= ~NETIF_F_GSO_MASK; -	dev->features |= NETIF_F_GSO_ROBUST; -	xennet_set_sg(dev, 0); - -	/* We need checksum offload to enable scatter/gather and TSO. */ -	if (!(dev->features & NETIF_F_IP_CSUM)) -		return; - -	if (!xennet_set_sg(dev, 1)) -		xennet_set_tso(dev, 1); -} -  static int xennet_connect(struct net_device *dev)  {  	struct netfront_info *np = netdev_priv(dev); @@ -1582,7 +1581,7 @@ static int xennet_connect(struct net_device *dev)  	if (err)  		return err; -	xennet_set_features(dev); +	netdev_update_features(dev);  	spin_lock_bh(&np->rx_lock);  	spin_lock_irq(&np->tx_lock); @@ -1710,9 +1709,6 @@ static void xennet_get_strings(struct net_device *dev, u32 stringset, u8 * data)  static const struct ethtool_ops xennet_ethtool_ops =  { -	.set_tx_csum = ethtool_op_set_tx_csum, -	.set_sg = xennet_set_sg, -	.set_tso = xennet_set_tso,  	.get_link = ethtool_op_get_link,  	.get_sset_count = xennet_get_sset_count, |