aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2011-11-28 06:16:50 -0500
committerDavid S. Miller <davem@davemloft.net>2011-11-29 00:26:25 -0500
commitb90e5794c5bdef91d26c623e992257947c506e35 (patch)
tree16bb31a00ad39d7fba91bb8d691bb0133e06312f /net/core/dev.c
parentdb62f684deeb291ab2533b99843d5df9a36b1f19 (diff)
net: dont call jump_label_dec from irq context
Igor Maravic reported an error caused by jump_label_dec() being called from IRQ context : BUG: sleeping function called from invalid context at kernel/mutex.c:271 in_atomic(): 1, irqs_disabled(): 0, pid: 0, name: swapper 1 lock held by swapper/0: #0: (&n->timer){+.-...}, at: [<ffffffff8107ce90>] call_timer_fn+0x0/0x340 Pid: 0, comm: swapper Not tainted 3.2.0-rc2-net-next-mpls+ #1 Call Trace: <IRQ> [<ffffffff8104f417>] __might_sleep+0x137/0x1f0 [<ffffffff816b9a2f>] mutex_lock_nested+0x2f/0x370 [<ffffffff810a89fd>] ? trace_hardirqs_off+0xd/0x10 [<ffffffff8109a37f>] ? local_clock+0x6f/0x80 [<ffffffff810a90a5>] ? lock_release_holdtime.part.22+0x15/0x1a0 [<ffffffff81557929>] ? sock_def_write_space+0x59/0x160 [<ffffffff815e936e>] ? arp_error_report+0x3e/0x90 [<ffffffff810969cd>] atomic_dec_and_mutex_lock+0x5d/0x80 [<ffffffff8112fc1d>] jump_label_dec+0x1d/0x50 [<ffffffff81566525>] net_disable_timestamp+0x15/0x20 [<ffffffff81557a75>] sock_disable_timestamp+0x45/0x50 [<ffffffff81557b00>] __sk_free+0x80/0x200 [<ffffffff815578d0>] ? sk_send_sigurg+0x70/0x70 [<ffffffff815e936e>] ? arp_error_report+0x3e/0x90 [<ffffffff81557cba>] sock_wfree+0x3a/0x70 [<ffffffff8155c2b0>] skb_release_head_state+0x70/0x120 [<ffffffff8155c0b6>] __kfree_skb+0x16/0x30 [<ffffffff8155c119>] kfree_skb+0x49/0x170 [<ffffffff815e936e>] arp_error_report+0x3e/0x90 [<ffffffff81575bd9>] neigh_invalidate+0x89/0xc0 [<ffffffff81578dbe>] neigh_timer_handler+0x9e/0x2a0 [<ffffffff81578d20>] ? neigh_update+0x640/0x640 [<ffffffff81073558>] __do_softirq+0xc8/0x3a0 Since jump_label_{inc|dec} must be called from process context only, we must defer jump_label_dec() if net_disable_timestamp() is called from interrupt context. Reported-by: Igor Maravic <igorm@etf.rs> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 962e3de25a35..c7ef6c5d3782 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1441,15 +1441,38 @@ int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
1441EXPORT_SYMBOL(call_netdevice_notifiers); 1441EXPORT_SYMBOL(call_netdevice_notifiers);
1442 1442
1443static struct jump_label_key netstamp_needed __read_mostly; 1443static struct jump_label_key netstamp_needed __read_mostly;
1444#ifdef HAVE_JUMP_LABEL
1445/* We are not allowed to call jump_label_dec() from irq context
1446 * If net_disable_timestamp() is called from irq context, defer the
1447 * jump_label_dec() calls.
1448 */
1449static atomic_t netstamp_needed_deferred;
1450#endif
1444 1451
1445void net_enable_timestamp(void) 1452void net_enable_timestamp(void)
1446{ 1453{
1454#ifdef HAVE_JUMP_LABEL
1455 int deferred = atomic_xchg(&netstamp_needed_deferred, 0);
1456
1457 if (deferred) {
1458 while (--deferred)
1459 jump_label_dec(&netstamp_needed);
1460 return;
1461 }
1462#endif
1463 WARN_ON(in_interrupt());
1447 jump_label_inc(&netstamp_needed); 1464 jump_label_inc(&netstamp_needed);
1448} 1465}
1449EXPORT_SYMBOL(net_enable_timestamp); 1466EXPORT_SYMBOL(net_enable_timestamp);
1450 1467
1451void net_disable_timestamp(void) 1468void net_disable_timestamp(void)
1452{ 1469{
1470#ifdef HAVE_JUMP_LABEL
1471 if (in_interrupt()) {
1472 atomic_inc(&netstamp_needed_deferred);
1473 return;
1474 }
1475#endif
1453 jump_label_dec(&netstamp_needed); 1476 jump_label_dec(&netstamp_needed);
1454} 1477}
1455EXPORT_SYMBOL(net_disable_timestamp); 1478EXPORT_SYMBOL(net_disable_timestamp);