aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorZoltan Kiss <zoltan.kiss@citrix.com>2014-03-06 16:48:31 -0500
committerDavid S. Miller <davem@davemloft.net>2014-03-07 15:57:21 -0500
commite9275f5e2df1b2098a8cc405d87b88b9affd73e6 (patch)
tree05898b0d8dab616b2936783964cae4f77b06af84 /drivers/net
parent093507885ae5dc0288af07fbb922d2f85b3a88a6 (diff)
xen-netback: Aggregate TX unmap operations
Unmapping causes TLB flushing, therefore we should make it in the largest possible batches. However we shouldn't starve the guest for too long. So if the guest has space for at least two big packets and we don't have at least a quarter ring to unmap, delay it for at most 1 milisec. Signed-off-by: Zoltan Kiss <zoltan.kiss@citrix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-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)