diff options
Diffstat (limited to 'drivers/net/xen-netback/interface.c')
| -rw-r--r-- | drivers/net/xen-netback/interface.c | 26 | 
1 files changed, 17 insertions, 9 deletions
| diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 829b26cd4549..8397f6c92451 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -165,13 +165,17 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)  {  	struct xenvif *vif = netdev_priv(dev);  	struct xenvif_queue *queue = NULL; -	unsigned int num_queues = vif->num_queues; +	unsigned int num_queues;  	u16 index;  	struct xenvif_rx_cb *cb;  	BUG_ON(skb->dev != dev); -	/* Drop the packet if queues are not set up */ +	/* Drop the packet if queues are not set up. +	 * This handler should be called inside an RCU read section +	 * so we don't need to enter it here explicitly. +	 */ +	num_queues = READ_ONCE(vif->num_queues);  	if (num_queues < 1)  		goto drop; @@ -222,18 +226,18 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev)  {  	struct xenvif *vif = netdev_priv(dev);  	struct xenvif_queue *queue = NULL; +	unsigned int num_queues;  	u64 rx_bytes = 0;  	u64 rx_packets = 0;  	u64 tx_bytes = 0;  	u64 tx_packets = 0;  	unsigned int index; -	spin_lock(&vif->lock); -	if (vif->queues == NULL) -		goto out; +	rcu_read_lock(); +	num_queues = READ_ONCE(vif->num_queues);  	/* Aggregate tx and rx stats from each queue */ -	for (index = 0; index < vif->num_queues; ++index) { +	for (index = 0; index < num_queues; ++index) {  		queue = &vif->queues[index];  		rx_bytes += queue->stats.rx_bytes;  		rx_packets += queue->stats.rx_packets; @@ -241,8 +245,7 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev)  		tx_packets += queue->stats.tx_packets;  	} -out: -	spin_unlock(&vif->lock); +	rcu_read_unlock();  	vif->dev->stats.rx_bytes = rx_bytes;  	vif->dev->stats.rx_packets = rx_packets; @@ -378,10 +381,13 @@ static void xenvif_get_ethtool_stats(struct net_device *dev,  				     struct ethtool_stats *stats, u64 * data)  {  	struct xenvif *vif = netdev_priv(dev); -	unsigned int num_queues = vif->num_queues; +	unsigned int num_queues;  	int i;  	unsigned int queue_index; +	rcu_read_lock(); +	num_queues = READ_ONCE(vif->num_queues); +  	for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++) {  		unsigned long accum = 0;  		for (queue_index = 0; queue_index < num_queues; ++queue_index) { @@ -390,6 +396,8 @@ static void xenvif_get_ethtool_stats(struct net_device *dev,  		}  		data[i] = accum;  	} + +	rcu_read_unlock();  }  static void xenvif_get_strings(struct net_device *dev, u32 stringset, u8 * data) | 

