diff options
-rw-r--r-- | drivers/net/xen-netback/netback.c | 29 |
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 | ||
1687 | static struct xen_netif_rx_response *make_rx_response(struct xenvif_queue *queue, | 1700 | static struct xen_netif_rx_response *make_rx_response(struct xenvif_queue *queue, |