From: David S. Miller Date: Fri, 28 Mar 2008 00:42:50 +0000 (-0700) Subject: [NET]: Use local_irq_{save,restore}() in napi_complete(). X-Git-Tag: v2.6.25-rc9~99^2~32 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=50fd4407b8bfbde7c1a0bfe4f24de7df37164342;p=linux-2.6 [NET]: Use local_irq_{save,restore}() in napi_complete(). Based upon a lockdep report. Since ->poll() can be invoked from netpoll with interrupts disabled, we must not unconditionally enable interrupts in napi_complete(). Instead we must use local_irq_{save,restore}(). Noticed by Peter Zijlstra: netpoll_poll() poll_napi() spin_trylock(&napi->poll_lock) poll_one_napi() napi->poll() := sky2_poll() napi_complete() local_irq_disable() local_irq_enable() <--- *BUG* irq_exit() do_softirq() net_rx_action() spin_lock(&napi->poll_lock) <--- Deadlock! Because we still hold the lock.... Signed-off-by: David S. Miller --- diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a2f003239c..fae6a7ecec 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -383,9 +383,11 @@ static inline void __napi_complete(struct napi_struct *n) static inline void napi_complete(struct napi_struct *n) { - local_irq_disable(); + unsigned long flags; + + local_irq_save(flags); __napi_complete(n); - local_irq_enable(); + local_irq_restore(flags); } /**