diff options
Diffstat (limited to 'drivers/net/virtio_net.c')
| -rw-r--r-- | drivers/net/virtio_net.c | 68 | 
1 files changed, 53 insertions, 15 deletions
| diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 765920905226..3e2c041d76ac 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1699,17 +1699,6 @@ static void virtnet_stats(struct net_device *dev,  	tot->rx_frame_errors = dev->stats.rx_frame_errors;  } -#ifdef CONFIG_NET_POLL_CONTROLLER -static void virtnet_netpoll(struct net_device *dev) -{ -	struct virtnet_info *vi = netdev_priv(dev); -	int i; - -	for (i = 0; i < vi->curr_queue_pairs; i++) -		napi_schedule(&vi->rq[i].napi); -} -#endif -  static void virtnet_ack_link_announce(struct virtnet_info *vi)  {  	rtnl_lock(); @@ -2181,6 +2170,53 @@ static int virtnet_get_link_ksettings(struct net_device *dev,  	return 0;  } +static int virtnet_set_coalesce(struct net_device *dev, +				struct ethtool_coalesce *ec) +{ +	struct ethtool_coalesce ec_default = { +		.cmd = ETHTOOL_SCOALESCE, +		.rx_max_coalesced_frames = 1, +	}; +	struct virtnet_info *vi = netdev_priv(dev); +	int i, napi_weight; + +	if (ec->tx_max_coalesced_frames > 1) +		return -EINVAL; + +	ec_default.tx_max_coalesced_frames = ec->tx_max_coalesced_frames; +	napi_weight = ec->tx_max_coalesced_frames ? NAPI_POLL_WEIGHT : 0; + +	/* disallow changes to fields not explicitly tested above */ +	if (memcmp(ec, &ec_default, sizeof(ec_default))) +		return -EINVAL; + +	if (napi_weight ^ vi->sq[0].napi.weight) { +		if (dev->flags & IFF_UP) +			return -EBUSY; +		for (i = 0; i < vi->max_queue_pairs; i++) +			vi->sq[i].napi.weight = napi_weight; +	} + +	return 0; +} + +static int virtnet_get_coalesce(struct net_device *dev, +				struct ethtool_coalesce *ec) +{ +	struct ethtool_coalesce ec_default = { +		.cmd = ETHTOOL_GCOALESCE, +		.rx_max_coalesced_frames = 1, +	}; +	struct virtnet_info *vi = netdev_priv(dev); + +	memcpy(ec, &ec_default, sizeof(ec_default)); + +	if (vi->sq[0].napi.weight) +		ec->tx_max_coalesced_frames = 1; + +	return 0; +} +  static void virtnet_init_settings(struct net_device *dev)  {  	struct virtnet_info *vi = netdev_priv(dev); @@ -2219,6 +2255,8 @@ static const struct ethtool_ops virtnet_ethtool_ops = {  	.get_ts_info = ethtool_op_get_ts_info,  	.get_link_ksettings = virtnet_get_link_ksettings,  	.set_link_ksettings = virtnet_set_link_ksettings, +	.set_coalesce = virtnet_set_coalesce, +	.get_coalesce = virtnet_get_coalesce,  };  static void virtnet_freeze_down(struct virtio_device *vdev) @@ -2229,8 +2267,9 @@ static void virtnet_freeze_down(struct virtio_device *vdev)  	/* Make sure no work handler is accessing the device */  	flush_work(&vi->config_work); +	netif_tx_lock_bh(vi->dev);  	netif_device_detach(vi->dev); -	netif_tx_disable(vi->dev); +	netif_tx_unlock_bh(vi->dev);  	cancel_delayed_work_sync(&vi->refill);  	if (netif_running(vi->dev)) { @@ -2266,7 +2305,9 @@ static int virtnet_restore_up(struct virtio_device *vdev)  		}  	} +	netif_tx_lock_bh(vi->dev);  	netif_device_attach(vi->dev); +	netif_tx_unlock_bh(vi->dev);  	return err;  } @@ -2447,9 +2488,6 @@ static const struct net_device_ops virtnet_netdev = {  	.ndo_get_stats64     = virtnet_stats,  	.ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,  	.ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid, -#ifdef CONFIG_NET_POLL_CONTROLLER -	.ndo_poll_controller = virtnet_netpoll, -#endif  	.ndo_bpf		= virtnet_xdp,  	.ndo_xdp_xmit		= virtnet_xdp_xmit,  	.ndo_features_check	= passthru_features_check, |