aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei Liu <wei.liu2@citrix.com>2013-10-28 08:07:57 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-20 15:27:46 -0500
commitfb1494fa72c8f40f63c56b0f0e77ea40db586448 (patch)
tree5da662ee603de9d3506f570533beff72a3d01a79
parent0b5be4967ce4d66e2f23103aa114e8170546578e (diff)
xen-netback: use jiffies_64 value to calculate credit timeout
[ Upstream commit 059dfa6a93b779516321e5112db9d7621b1367ba ] time_after_eq() only works if the delta is < MAX_ULONG/2. For a 32bit Dom0, if netfront sends packets at a very low rate, the time between subsequent calls to tx_credit_exceeded() may exceed MAX_ULONG/2 and the test for timer_after_eq() will be incorrect. Credit will not be replenished and the guest may become unable to send packets (e.g., if prior to the long gap, all credit was exhausted). Use jiffies_64 variant to mitigate this problem for 32bit Dom0. Suggested-by: Jan Beulich <jbeulich@suse.com> Signed-off-by: Wei Liu <wei.liu2@citrix.com> Reviewed-by: David Vrabel <david.vrabel@citrix.com> Cc: Ian Campbell <ian.campbell@citrix.com> Cc: Jason Luan <jianhai.luan@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/xen-netback/common.h1
-rw-r--r--drivers/net/xen-netback/interface.c3
-rw-r--r--drivers/net/xen-netback/netback.c10
3 files changed, 7 insertions, 7 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 1a285083d24a..f2faa779e3fe 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -88,6 +88,7 @@ struct xenvif {
88 unsigned long credit_usec; 88 unsigned long credit_usec;
89 unsigned long remaining_credit; 89 unsigned long remaining_credit;
90 struct timer_list credit_timeout; 90 struct timer_list credit_timeout;
91 u64 credit_window_start;
91 92
92 /* Statistics */ 93 /* Statistics */
93 unsigned long rx_gso_checksum_fixup; 94 unsigned long rx_gso_checksum_fixup;
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 3a294c2528d5..c4a2eb2cd8a0 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -275,8 +275,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
275 vif->credit_bytes = vif->remaining_credit = ~0UL; 275 vif->credit_bytes = vif->remaining_credit = ~0UL;
276 vif->credit_usec = 0UL; 276 vif->credit_usec = 0UL;
277 init_timer(&vif->credit_timeout); 277 init_timer(&vif->credit_timeout);
278 /* Initialize 'expires' now: it's used to track the credit window. */ 278 vif->credit_window_start = get_jiffies_64();
279 vif->credit_timeout.expires = jiffies;
280 279
281 dev->netdev_ops = &xenvif_netdev_ops; 280 dev->netdev_ops = &xenvif_netdev_ops;
282 dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; 281 dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 0071f211a08a..36efb418c26f 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1423,9 +1423,8 @@ out:
1423 1423
1424static bool tx_credit_exceeded(struct xenvif *vif, unsigned size) 1424static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
1425{ 1425{
1426 unsigned long now = jiffies; 1426 u64 now = get_jiffies_64();
1427 unsigned long next_credit = 1427 u64 next_credit = vif->credit_window_start +
1428 vif->credit_timeout.expires +
1429 msecs_to_jiffies(vif->credit_usec / 1000); 1428 msecs_to_jiffies(vif->credit_usec / 1000);
1430 1429
1431 /* Timer could already be pending in rare cases. */ 1430 /* Timer could already be pending in rare cases. */
@@ -1433,8 +1432,8 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
1433 return true; 1432 return true;
1434 1433
1435 /* Passed the point where we can replenish credit? */ 1434 /* Passed the point where we can replenish credit? */
1436 if (time_after_eq(now, next_credit)) { 1435 if (time_after_eq64(now, next_credit)) {
1437 vif->credit_timeout.expires = now; 1436 vif->credit_window_start = now;
1438 tx_add_credit(vif); 1437 tx_add_credit(vif);
1439 } 1438 }
1440 1439
@@ -1446,6 +1445,7 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
1446 tx_credit_callback; 1445 tx_credit_callback;
1447 mod_timer(&vif->credit_timeout, 1446 mod_timer(&vif->credit_timeout,
1448 next_credit); 1447 next_credit);
1448 vif->credit_window_start = next_credit;
1449 1449
1450 return true; 1450 return true;
1451 } 1451 }