diff options
Diffstat (limited to 'drivers/net/xen-netback/netback.c')
-rw-r--r-- | drivers/net/xen-netback/netback.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index aa2093325be1..08f65996534c 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -1525,10 +1525,12 @@ static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *s | |||
1525 | /* remove traces of mapped pages and frag_list */ | 1525 | /* remove traces of mapped pages and frag_list */ |
1526 | skb_frag_list_init(skb); | 1526 | skb_frag_list_init(skb); |
1527 | uarg = skb_shinfo(skb)->destructor_arg; | 1527 | uarg = skb_shinfo(skb)->destructor_arg; |
1528 | /* increase inflight counter to offset decrement in callback */ | ||
1529 | atomic_inc(&queue->inflight_packets); | ||
1528 | uarg->callback(uarg, true); | 1530 | uarg->callback(uarg, true); |
1529 | skb_shinfo(skb)->destructor_arg = NULL; | 1531 | skb_shinfo(skb)->destructor_arg = NULL; |
1530 | 1532 | ||
1531 | skb_shinfo(nskb)->tx_flags |= SKBTX_DEV_ZEROCOPY; | 1533 | xenvif_skb_zerocopy_prepare(queue, nskb); |
1532 | kfree_skb(nskb); | 1534 | kfree_skb(nskb); |
1533 | 1535 | ||
1534 | return 0; | 1536 | return 0; |
@@ -1589,7 +1591,7 @@ static int xenvif_tx_submit(struct xenvif_queue *queue) | |||
1589 | if (net_ratelimit()) | 1591 | if (net_ratelimit()) |
1590 | netdev_err(queue->vif->dev, | 1592 | netdev_err(queue->vif->dev, |
1591 | "Not enough memory to consolidate frag_list!\n"); | 1593 | "Not enough memory to consolidate frag_list!\n"); |
1592 | skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; | 1594 | xenvif_skb_zerocopy_prepare(queue, skb); |
1593 | kfree_skb(skb); | 1595 | kfree_skb(skb); |
1594 | continue; | 1596 | continue; |
1595 | } | 1597 | } |
@@ -1609,7 +1611,7 @@ static int xenvif_tx_submit(struct xenvif_queue *queue) | |||
1609 | "Can't setup checksum in net_tx_action\n"); | 1611 | "Can't setup checksum in net_tx_action\n"); |
1610 | /* We have to set this flag to trigger the callback */ | 1612 | /* We have to set this flag to trigger the callback */ |
1611 | if (skb_shinfo(skb)->destructor_arg) | 1613 | if (skb_shinfo(skb)->destructor_arg) |
1612 | skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; | 1614 | xenvif_skb_zerocopy_prepare(queue, skb); |
1613 | kfree_skb(skb); | 1615 | kfree_skb(skb); |
1614 | continue; | 1616 | continue; |
1615 | } | 1617 | } |
@@ -1641,7 +1643,7 @@ static int xenvif_tx_submit(struct xenvif_queue *queue) | |||
1641 | * skb. E.g. the __pskb_pull_tail earlier can do such thing. | 1643 | * skb. E.g. the __pskb_pull_tail earlier can do such thing. |
1642 | */ | 1644 | */ |
1643 | if (skb_shinfo(skb)->destructor_arg) { | 1645 | if (skb_shinfo(skb)->destructor_arg) { |
1644 | skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; | 1646 | xenvif_skb_zerocopy_prepare(queue, skb); |
1645 | queue->stats.tx_zerocopy_sent++; | 1647 | queue->stats.tx_zerocopy_sent++; |
1646 | } | 1648 | } |
1647 | 1649 | ||
@@ -1681,6 +1683,7 @@ void xenvif_zerocopy_callback(struct ubuf_info *ubuf, bool zerocopy_success) | |||
1681 | queue->stats.tx_zerocopy_success++; | 1683 | queue->stats.tx_zerocopy_success++; |
1682 | else | 1684 | else |
1683 | queue->stats.tx_zerocopy_fail++; | 1685 | queue->stats.tx_zerocopy_fail++; |
1686 | xenvif_skb_zerocopy_complete(queue); | ||
1684 | } | 1687 | } |
1685 | 1688 | ||
1686 | static inline void xenvif_tx_dealloc_action(struct xenvif_queue *queue) | 1689 | static inline void xenvif_tx_dealloc_action(struct xenvif_queue *queue) |
@@ -2025,9 +2028,15 @@ int xenvif_kthread_guest_rx(void *data) | |||
2025 | * context so we defer it here, if this thread is | 2028 | * context so we defer it here, if this thread is |
2026 | * associated with queue 0. | 2029 | * associated with queue 0. |
2027 | */ | 2030 | */ |
2028 | if (unlikely(queue->vif->disabled && queue->id == 0)) | 2031 | if (unlikely(queue->vif->disabled && queue->id == 0)) { |
2029 | xenvif_carrier_off(queue->vif); | 2032 | xenvif_carrier_off(queue->vif); |
2030 | else if (unlikely(test_and_clear_bit(QUEUE_STATUS_RX_PURGE_EVENT, | 2033 | } else if (unlikely(queue->vif->disabled)) { |
2034 | /* kthread_stop() would be called upon this thread soon, | ||
2035 | * be a bit proactive | ||
2036 | */ | ||
2037 | skb_queue_purge(&queue->rx_queue); | ||
2038 | queue->rx_last_skb_slots = 0; | ||
2039 | } else if (unlikely(test_and_clear_bit(QUEUE_STATUS_RX_PURGE_EVENT, | ||
2031 | &queue->status))) { | 2040 | &queue->status))) { |
2032 | xenvif_rx_purge_event(queue); | 2041 | xenvif_rx_purge_event(queue); |
2033 | } else if (!netif_carrier_ok(queue->vif->dev)) { | 2042 | } else if (!netif_carrier_ok(queue->vif->dev)) { |
@@ -2052,15 +2061,24 @@ int xenvif_kthread_guest_rx(void *data) | |||
2052 | return 0; | 2061 | return 0; |
2053 | } | 2062 | } |
2054 | 2063 | ||
2064 | static bool xenvif_dealloc_kthread_should_stop(struct xenvif_queue *queue) | ||
2065 | { | ||
2066 | /* Dealloc thread must remain running until all inflight | ||
2067 | * packets complete. | ||
2068 | */ | ||
2069 | return kthread_should_stop() && | ||
2070 | !atomic_read(&queue->inflight_packets); | ||
2071 | } | ||
2072 | |||
2055 | int xenvif_dealloc_kthread(void *data) | 2073 | int xenvif_dealloc_kthread(void *data) |
2056 | { | 2074 | { |
2057 | struct xenvif_queue *queue = data; | 2075 | struct xenvif_queue *queue = data; |
2058 | 2076 | ||
2059 | while (!kthread_should_stop()) { | 2077 | for (;;) { |
2060 | wait_event_interruptible(queue->dealloc_wq, | 2078 | wait_event_interruptible(queue->dealloc_wq, |
2061 | tx_dealloc_work_todo(queue) || | 2079 | tx_dealloc_work_todo(queue) || |
2062 | kthread_should_stop()); | 2080 | xenvif_dealloc_kthread_should_stop(queue)); |
2063 | if (kthread_should_stop()) | 2081 | if (xenvif_dealloc_kthread_should_stop(queue)) |
2064 | break; | 2082 | break; |
2065 | 2083 | ||
2066 | xenvif_tx_dealloc_action(queue); | 2084 | xenvif_tx_dealloc_action(queue); |