aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index e63bf61b19be..8637b2b71f3d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1698,27 +1698,54 @@ EXPORT_SYMBOL_GPL(net_dec_egress_queue);
1698static struct static_key netstamp_needed __read_mostly; 1698static struct static_key netstamp_needed __read_mostly;
1699#ifdef HAVE_JUMP_LABEL 1699#ifdef HAVE_JUMP_LABEL
1700static atomic_t netstamp_needed_deferred; 1700static atomic_t netstamp_needed_deferred;
1701static atomic_t netstamp_wanted;
1701static void netstamp_clear(struct work_struct *work) 1702static void netstamp_clear(struct work_struct *work)
1702{ 1703{
1703 int deferred = atomic_xchg(&netstamp_needed_deferred, 0); 1704 int deferred = atomic_xchg(&netstamp_needed_deferred, 0);
1705 int wanted;
1704 1706
1705 while (deferred--) 1707 wanted = atomic_add_return(deferred, &netstamp_wanted);
1706 static_key_slow_dec(&netstamp_needed); 1708 if (wanted > 0)
1709 static_key_enable(&netstamp_needed);
1710 else
1711 static_key_disable(&netstamp_needed);
1707} 1712}
1708static DECLARE_WORK(netstamp_work, netstamp_clear); 1713static DECLARE_WORK(netstamp_work, netstamp_clear);
1709#endif 1714#endif
1710 1715
1711void net_enable_timestamp(void) 1716void net_enable_timestamp(void)
1712{ 1717{
1718#ifdef HAVE_JUMP_LABEL
1719 int wanted;
1720
1721 while (1) {
1722 wanted = atomic_read(&netstamp_wanted);
1723 if (wanted <= 0)
1724 break;
1725 if (atomic_cmpxchg(&netstamp_wanted, wanted, wanted + 1) == wanted)
1726 return;
1727 }
1728 atomic_inc(&netstamp_needed_deferred);
1729 schedule_work(&netstamp_work);
1730#else
1713 static_key_slow_inc(&netstamp_needed); 1731 static_key_slow_inc(&netstamp_needed);
1732#endif
1714} 1733}
1715EXPORT_SYMBOL(net_enable_timestamp); 1734EXPORT_SYMBOL(net_enable_timestamp);
1716 1735
1717void net_disable_timestamp(void) 1736void net_disable_timestamp(void)
1718{ 1737{
1719#ifdef HAVE_JUMP_LABEL 1738#ifdef HAVE_JUMP_LABEL
1720 /* net_disable_timestamp() can be called from non process context */ 1739 int wanted;
1721 atomic_inc(&netstamp_needed_deferred); 1740
1741 while (1) {
1742 wanted = atomic_read(&netstamp_wanted);
1743 if (wanted <= 1)
1744 break;
1745 if (atomic_cmpxchg(&netstamp_wanted, wanted, wanted - 1) == wanted)
1746 return;
1747 }
1748 atomic_dec(&netstamp_needed_deferred);
1722 schedule_work(&netstamp_work); 1749 schedule_work(&netstamp_work);
1723#else 1750#else
1724 static_key_slow_dec(&netstamp_needed); 1751 static_key_slow_dec(&netstamp_needed);