Merge branch 'xen-netfront'

David Vrabel says:

====================
xen-netfront: multi-queue related locking fixes

Two fixes to the per-queue locking bugs in xen-netfront that were
introduced in 3.16-rc1 with the multi-queue support.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2014-07-08 11:21:10 -07:00
commit ff883aeb42
1 changed files with 16 additions and 11 deletions

View File

@ -1439,16 +1439,11 @@ static void xennet_disconnect_backend(struct netfront_info *info)
unsigned int i = 0;
unsigned int num_queues = info->netdev->real_num_tx_queues;
netif_carrier_off(info->netdev);
for (i = 0; i < num_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))
unbind_from_irqhandler(queue->tx_irq, queue);
if (queue->tx_irq && (queue->tx_irq != queue->rx_irq)) {
@ -1458,6 +1453,8 @@ static void xennet_disconnect_backend(struct netfront_info *info)
queue->tx_evtchn = queue->rx_evtchn = 0;
queue->tx_irq = queue->rx_irq = 0;
napi_synchronize(&queue->napi);
/* End access and free the pages */
xennet_end_access(queue->tx_ring_ref, queue->tx.sring);
xennet_end_access(queue->rx_ring_ref, queue->rx.sring);
@ -2046,13 +2043,15 @@ static int xennet_connect(struct net_device *dev)
/* By now, the queue structures have been set up */
for (j = 0; j < num_queues; ++j) {
queue = &np->queues[j];
spin_lock_bh(&queue->rx_lock);
spin_lock_irq(&queue->tx_lock);
/* Step 1: Discard all pending TX packet fragments. */
spin_lock_irq(&queue->tx_lock);
xennet_release_tx_bufs(queue);
spin_unlock_irq(&queue->tx_lock);
/* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
spin_lock_bh(&queue->rx_lock);
for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
skb_frag_t *frag;
const struct page *page;
@ -2076,6 +2075,8 @@ static int xennet_connect(struct net_device *dev)
}
queue->rx.req_prod_pvt = requeue_idx;
spin_unlock_bh(&queue->rx_lock);
}
/*
@ -2087,13 +2088,17 @@ static int xennet_connect(struct net_device *dev)
netif_carrier_on(np->netdev);
for (j = 0; j < num_queues; ++j) {
queue = &np->queues[j];
notify_remote_via_irq(queue->tx_irq);
if (queue->tx_irq != queue->rx_irq)
notify_remote_via_irq(queue->rx_irq);
xennet_tx_buf_gc(queue);
xennet_alloc_rx_buffers(queue);
spin_lock_irq(&queue->tx_lock);
xennet_tx_buf_gc(queue);
spin_unlock_irq(&queue->tx_lock);
spin_lock_bh(&queue->rx_lock);
xennet_alloc_rx_buffers(queue);
spin_unlock_bh(&queue->rx_lock);
}