aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/xen-netback/common.h2
-rw-r--r--drivers/net/xen-netback/interface.c2
-rw-r--r--drivers/net/xen-netback/netback.c34
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
136static 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
136bool xenvif_rx_ring_slots_available(struct xenvif *vif, int needed) 141bool 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
1724static 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
1719static inline bool tx_dealloc_work_todo(struct xenvif *vif) 1732static 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
1724void xenvif_unmap_frontend_rings(struct xenvif *vif) 1756void xenvif_unmap_frontend_rings(struct xenvif *vif)