Commit f9feb1e6 authored by David Vrabel's avatar David Vrabel Committed by David S. Miller

xen-netfront: call netif_carrier_off() only once when disconnecting

In xennet_disconnect_backend(), netif_carrier_off() was called once
per queue when it needs to only be called once.

The queue locking around the netif_carrier_off() call looked very
odd. I think they were supposed to synchronize any NAPI instances with
the expectation that no further NAPI instances would be scheduled
because of the carrier being off (see the check in
xennet_rx_interrupt()).  But I can't easily tell if this works
correctly.

Instead, add a napi_synchronize() call after disabling the interrupts.
This is obviously correct as with no Rx interrupts, no further NAPI
instances will be scheduled.
Signed-off-by: default avatarDavid Vrabel <david.vrabel@citrix.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f50b4076
...@@ -1439,16 +1439,11 @@ static void xennet_disconnect_backend(struct netfront_info *info) ...@@ -1439,16 +1439,11 @@ static void xennet_disconnect_backend(struct netfront_info *info)
unsigned int i = 0; unsigned int i = 0;
unsigned int num_queues = info->netdev->real_num_tx_queues; unsigned int num_queues = info->netdev->real_num_tx_queues;
netif_carrier_off(info->netdev);
for (i = 0; i < num_queues; ++i) { for (i = 0; i < num_queues; ++i) {
struct netfront_queue *queue = &info->queues[i]; struct netfront_queue *queue = &info->queues[i];
/* Stop old i/f to prevent errors whilst we rebuild the state. */
spin_lock_bh(&queue->rx_lock);
spin_lock_irq(&queue->tx_lock);
netif_carrier_off(queue->info->netdev);
spin_unlock_irq(&queue->tx_lock);
spin_unlock_bh(&queue->rx_lock);
if (queue->tx_irq && (queue->tx_irq == queue->rx_irq)) if (queue->tx_irq && (queue->tx_irq == queue->rx_irq))
unbind_from_irqhandler(queue->tx_irq, queue); unbind_from_irqhandler(queue->tx_irq, queue);
if (queue->tx_irq && (queue->tx_irq != queue->rx_irq)) { if (queue->tx_irq && (queue->tx_irq != queue->rx_irq)) {
...@@ -1458,6 +1453,8 @@ static void xennet_disconnect_backend(struct netfront_info *info) ...@@ -1458,6 +1453,8 @@ static void xennet_disconnect_backend(struct netfront_info *info)
queue->tx_evtchn = queue->rx_evtchn = 0; queue->tx_evtchn = queue->rx_evtchn = 0;
queue->tx_irq = queue->rx_irq = 0; queue->tx_irq = queue->rx_irq = 0;
napi_synchronize(&queue->napi);
/* End access and free the pages */ /* End access and free the pages */
xennet_end_access(queue->tx_ring_ref, queue->tx.sring); xennet_end_access(queue->tx_ring_ref, queue->tx.sring);
xennet_end_access(queue->rx_ring_ref, queue->rx.sring); xennet_end_access(queue->rx_ring_ref, queue->rx.sring);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment