aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2015-02-24 06:17:59 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-24 16:24:22 -0500
commit7fbb9d8415d4a51cf542e87cf3a717a9f7e6aedc (patch)
treede9e7b9db0b88366ca381c2c405d32ba75a7a454
parent41a50d621a321b4c15273cc1b5ed41437f4acdfb (diff)
xen-netback: release pending index before pushing Tx responses
If the pending indexes are released /after/ pushing the Tx response then a stale pending index may be used if a new Tx request is immediately pushed by the frontend. The may cause various WARNINGs or BUGs if the stale pending index is actually still in use. Fix this by releasing the pending index before pushing the Tx response. The full barrier for the pending ring update is not required since the the Tx response push already has a suitable write barrier. Signed-off-by: David Vrabel <david.vrabel@citrix.com> Reviewed-by: Wei Liu <wei.liu2@citrix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/xen-netback/netback.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index f7a31d2cb3f1..c4d68d768408 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -655,9 +655,15 @@ static void xenvif_tx_err(struct xenvif_queue *queue,
655 unsigned long flags; 655 unsigned long flags;
656 656
657 do { 657 do {
658 int notify;
659
658 spin_lock_irqsave(&queue->response_lock, flags); 660 spin_lock_irqsave(&queue->response_lock, flags);
659 make_tx_response(queue, txp, XEN_NETIF_RSP_ERROR); 661 make_tx_response(queue, txp, XEN_NETIF_RSP_ERROR);
662 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&queue->tx, notify);
660 spin_unlock_irqrestore(&queue->response_lock, flags); 663 spin_unlock_irqrestore(&queue->response_lock, flags);
664 if (notify)
665 notify_remote_via_irq(queue->tx_irq);
666
661 if (cons == end) 667 if (cons == end)
662 break; 668 break;
663 txp = RING_GET_REQUEST(&queue->tx, cons++); 669 txp = RING_GET_REQUEST(&queue->tx, cons++);
@@ -1649,17 +1655,28 @@ static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
1649{ 1655{
1650 struct pending_tx_info *pending_tx_info; 1656 struct pending_tx_info *pending_tx_info;
1651 pending_ring_idx_t index; 1657 pending_ring_idx_t index;
1658 int notify;
1652 unsigned long flags; 1659 unsigned long flags;
1653 1660
1654 pending_tx_info = &queue->pending_tx_info[pending_idx]; 1661 pending_tx_info = &queue->pending_tx_info[pending_idx];
1662
1655 spin_lock_irqsave(&queue->response_lock, flags); 1663 spin_lock_irqsave(&queue->response_lock, flags);
1664
1656 make_tx_response(queue, &pending_tx_info->req, status); 1665 make_tx_response(queue, &pending_tx_info->req, status);
1657 index = pending_index(queue->pending_prod); 1666
1667 /* Release the pending index before pusing the Tx response so
1668 * its available before a new Tx request is pushed by the
1669 * frontend.
1670 */
1671 index = pending_index(queue->pending_prod++);
1658 queue->pending_ring[index] = pending_idx; 1672 queue->pending_ring[index] = pending_idx;
1659 /* TX shouldn't use the index before we give it back here */ 1673
1660 mb(); 1674 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&queue->tx, notify);
1661 queue->pending_prod++; 1675
1662 spin_unlock_irqrestore(&queue->response_lock, flags); 1676 spin_unlock_irqrestore(&queue->response_lock, flags);
1677
1678 if (notify)
1679 notify_remote_via_irq(queue->tx_irq);
1663} 1680}
1664 1681
1665 1682
@@ -1669,7 +1686,6 @@ static void make_tx_response(struct xenvif_queue *queue,
1669{ 1686{
1670 RING_IDX i = queue->tx.rsp_prod_pvt; 1687 RING_IDX i = queue->tx.rsp_prod_pvt;
1671 struct xen_netif_tx_response *resp; 1688 struct xen_netif_tx_response *resp;
1672 int notify;
1673 1689
1674 resp = RING_GET_RESPONSE(&queue->tx, i); 1690 resp = RING_GET_RESPONSE(&queue->tx, i);
1675 resp->id = txp->id; 1691 resp->id = txp->id;
@@ -1679,9 +1695,6 @@ static void make_tx_response(struct xenvif_queue *queue,
1679 RING_GET_RESPONSE(&queue->tx, ++i)->status = XEN_NETIF_RSP_NULL; 1695 RING_GET_RESPONSE(&queue->tx, ++i)->status = XEN_NETIF_RSP_NULL;
1680 1696
1681 queue->tx.rsp_prod_pvt = ++i; 1697 queue->tx.rsp_prod_pvt = ++i;
1682 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&queue->tx, notify);
1683 if (notify)
1684 notify_remote_via_irq(queue->tx_irq);
1685} 1698}
1686 1699
1687static struct xen_netif_rx_response *make_rx_response(struct xenvif_queue *queue, 1700static struct xen_netif_rx_response *make_rx_response(struct xenvif_queue *queue,