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) | |||
165 | { | 165 | { |
166 | struct xenvif *vif = netdev_priv(dev); | 166 | struct xenvif *vif = netdev_priv(dev); |
167 | struct xenvif_queue *queue = NULL; | 167 | struct xenvif_queue *queue = NULL; |
168 | unsigned int num_queues = vif->num_queues; | 168 | unsigned int num_queues; |
169 | u16 index; | 169 | u16 index; |
170 | struct xenvif_rx_cb *cb; | 170 | struct xenvif_rx_cb *cb; |
171 | 171 | ||
172 | BUG_ON(skb->dev != dev); | 172 | BUG_ON(skb->dev != dev); |
173 | 173 | ||
174 | /* Drop the packet if queues are not set up */ | 174 | /* Drop the packet if queues are not set up. |
175 | * This handler should be called inside an RCU read section | ||
176 | * so we don't need to enter it here explicitly. | ||
177 | */ | ||
178 | num_queues = READ_ONCE(vif->num_queues); | ||
175 | if (num_queues < 1) | 179 | if (num_queues < 1) |
176 | goto drop; | 180 | goto drop; |
177 | 181 | ||
@@ -222,18 +226,18 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev) | |||
222 | { | 226 | { |
223 | struct xenvif *vif = netdev_priv(dev); | 227 | struct xenvif *vif = netdev_priv(dev); |
224 | struct xenvif_queue *queue = NULL; | 228 | struct xenvif_queue *queue = NULL; |
229 | unsigned int num_queues; | ||
225 | u64 rx_bytes = 0; | 230 | u64 rx_bytes = 0; |
226 | u64 rx_packets = 0; | 231 | u64 rx_packets = 0; |
227 | u64 tx_bytes = 0; | 232 | u64 tx_bytes = 0; |
228 | u64 tx_packets = 0; | 233 | u64 tx_packets = 0; |
229 | unsigned int index; | 234 | unsigned int index; |
230 | 235 | ||
231 | spin_lock(&vif->lock); | 236 | rcu_read_lock(); |
232 | if (vif->queues == NULL) | 237 | num_queues = READ_ONCE(vif->num_queues); |
233 | goto out; | ||
234 | 238 | ||
235 | /* Aggregate tx and rx stats from each queue */ | 239 | /* Aggregate tx and rx stats from each queue */ |
236 | for (index = 0; index < vif->num_queues; ++index) { | 240 | for (index = 0; index < num_queues; ++index) { |
237 | queue = &vif->queues[index]; | 241 | queue = &vif->queues[index]; |
238 | rx_bytes += queue->stats.rx_bytes; | 242 | rx_bytes += queue->stats.rx_bytes; |
239 | rx_packets += queue->stats.rx_packets; | 243 | rx_packets += queue->stats.rx_packets; |
@@ -241,8 +245,7 @@ static struct net_device_stats *xenvif_get_stats(struct net_device *dev) | |||
241 | tx_packets += queue->stats.tx_packets; | 245 | tx_packets += queue->stats.tx_packets; |
242 | } | 246 | } |
243 | 247 | ||
244 | out: | 248 | rcu_read_unlock(); |
245 | spin_unlock(&vif->lock); | ||
246 | 249 | ||
247 | vif->dev->stats.rx_bytes = rx_bytes; | 250 | vif->dev->stats.rx_bytes = rx_bytes; |
248 | vif->dev->stats.rx_packets = rx_packets; | 251 | vif->dev->stats.rx_packets = rx_packets; |
@@ -378,10 +381,13 @@ static void xenvif_get_ethtool_stats(struct net_device *dev, | |||
378 | struct ethtool_stats *stats, u64 * data) | 381 | struct ethtool_stats *stats, u64 * data) |
379 | { | 382 | { |
380 | struct xenvif *vif = netdev_priv(dev); | 383 | struct xenvif *vif = netdev_priv(dev); |
381 | unsigned int num_queues = vif->num_queues; | 384 | unsigned int num_queues; |
382 | int i; | 385 | int i; |
383 | unsigned int queue_index; | 386 | unsigned int queue_index; |
384 | 387 | ||
388 | rcu_read_lock(); | ||
389 | num_queues = READ_ONCE(vif->num_queues); | ||
390 | |||
385 | for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++) { | 391 | for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++) { |
386 | unsigned long accum = 0; | 392 | unsigned long accum = 0; |
387 | for (queue_index = 0; queue_index < num_queues; ++queue_index) { | 393 | for (queue_index = 0; queue_index < num_queues; ++queue_index) { |
@@ -390,6 +396,8 @@ static void xenvif_get_ethtool_stats(struct net_device *dev, | |||
390 | } | 396 | } |
391 | data[i] = accum; | 397 | data[i] = accum; |
392 | } | 398 | } |
399 | |||
400 | rcu_read_unlock(); | ||
393 | } | 401 | } |
394 | 402 | ||
395 | static void xenvif_get_strings(struct net_device *dev, u32 stringset, u8 * data) | 403 | static void xenvif_get_strings(struct net_device *dev, u32 stringset, u8 * data) |