diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/xen-netback/common.h | 2 | ||||
-rw-r--r-- | drivers/net/xen-netback/interface.c | 2 | ||||
-rw-r--r-- | drivers/net/xen-netback/netback.c | 34 |
3 files changed, 37 insertions, 1 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 0355f8767e3b..bef37be402b8 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h | |||
@@ -137,6 +137,8 @@ struct xenvif { | |||
137 | u16 dealloc_ring[MAX_PENDING_REQS]; | 137 | u16 dealloc_ring[MAX_PENDING_REQS]; |
138 | struct task_struct *dealloc_task; | 138 | struct task_struct *dealloc_task; |
139 | wait_queue_head_t dealloc_wq; | 139 | wait_queue_head_t dealloc_wq; |
140 | struct timer_list dealloc_delay; | ||
141 | bool dealloc_delay_timed_out; | ||
140 | 142 | ||
141 | /* Use kthread for guest RX */ | 143 | /* Use kthread for guest RX */ |
142 | struct task_struct *task; | 144 | struct task_struct *task; |
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 9cc9f638f442..83a71ac5b93a 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c | |||
@@ -408,6 +408,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, | |||
408 | .desc = i }; | 408 | .desc = i }; |
409 | vif->grant_tx_handle[i] = NETBACK_INVALID_HANDLE; | 409 | vif->grant_tx_handle[i] = NETBACK_INVALID_HANDLE; |
410 | } | 410 | } |
411 | init_timer(&vif->dealloc_delay); | ||
411 | 412 | ||
412 | /* | 413 | /* |
413 | * Initialise a dummy MAC address. We choose the numerically | 414 | * Initialise a dummy MAC address. We choose the numerically |
@@ -556,6 +557,7 @@ void xenvif_disconnect(struct xenvif *vif) | |||
556 | } | 557 | } |
557 | 558 | ||
558 | if (vif->dealloc_task) { | 559 | if (vif->dealloc_task) { |
560 | del_timer_sync(&vif->dealloc_delay); | ||
559 | kthread_stop(vif->dealloc_task); | 561 | kthread_stop(vif->dealloc_task); |
560 | vif->dealloc_task = NULL; | 562 | vif->dealloc_task = NULL; |
561 | } | 563 | } |
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 8518a0d1f6f9..bc943205a691 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -133,6 +133,11 @@ static inline pending_ring_idx_t pending_index(unsigned i) | |||
133 | return i & (MAX_PENDING_REQS-1); | 133 | return i & (MAX_PENDING_REQS-1); |
134 | } | 134 | } |
135 | 135 | ||
136 | static inline pending_ring_idx_t nr_free_slots(struct xen_netif_tx_back_ring *ring) | ||
137 | { | ||
138 | return ring->nr_ents - (ring->sring->req_prod - ring->rsp_prod_pvt); | ||
139 | } | ||
140 | |||
136 | bool xenvif_rx_ring_slots_available(struct xenvif *vif, int needed) | 141 | bool xenvif_rx_ring_slots_available(struct xenvif *vif, int needed) |
137 | { | 142 | { |
138 | RING_IDX prod, cons; | 143 | RING_IDX prod, cons; |
@@ -1716,9 +1721,36 @@ static inline int tx_work_todo(struct xenvif *vif) | |||
1716 | return 0; | 1721 | return 0; |
1717 | } | 1722 | } |
1718 | 1723 | ||
1724 | static void xenvif_dealloc_delay(unsigned long data) | ||
1725 | { | ||
1726 | struct xenvif *vif = (struct xenvif *)data; | ||
1727 | |||
1728 | vif->dealloc_delay_timed_out = true; | ||
1729 | wake_up(&vif->dealloc_wq); | ||
1730 | } | ||
1731 | |||
1719 | static inline bool tx_dealloc_work_todo(struct xenvif *vif) | 1732 | static inline bool tx_dealloc_work_todo(struct xenvif *vif) |
1720 | { | 1733 | { |
1721 | return vif->dealloc_cons != vif->dealloc_prod; | 1734 | if (vif->dealloc_cons != vif->dealloc_prod) { |
1735 | if ((nr_free_slots(&vif->tx) > 2 * XEN_NETBK_LEGACY_SLOTS_MAX) && | ||
1736 | (vif->dealloc_prod - vif->dealloc_cons < MAX_PENDING_REQS / 4) && | ||
1737 | !vif->dealloc_delay_timed_out) { | ||
1738 | if (!timer_pending(&vif->dealloc_delay)) { | ||
1739 | vif->dealloc_delay.function = | ||
1740 | xenvif_dealloc_delay; | ||
1741 | vif->dealloc_delay.data = (unsigned long)vif; | ||
1742 | mod_timer(&vif->dealloc_delay, | ||
1743 | jiffies + msecs_to_jiffies(1)); | ||
1744 | |||
1745 | } | ||
1746 | return false; | ||
1747 | } | ||
1748 | del_timer_sync(&vif->dealloc_delay); | ||
1749 | vif->dealloc_delay_timed_out = false; | ||
1750 | return true; | ||
1751 | } | ||
1752 | |||
1753 | return false; | ||
1722 | } | 1754 | } |
1723 | 1755 | ||
1724 | void xenvif_unmap_frontend_rings(struct xenvif *vif) | 1756 | void xenvif_unmap_frontend_rings(struct xenvif *vif) |