aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/netpoll.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2013-04-30 01:35:05 -0400
committerDavid S. Miller <davem@davemloft.net>2013-05-01 15:00:24 -0400
commitbd7c4b604a6cd707803c7c6ba142bfa131f9a9f3 (patch)
treee59ba7ef1be91d822a39ee659c83e445ec607f3e /net/core/netpoll.c
parentae6164adeb559db1828d4abd917971b61130f72e (diff)
netpoll: convert mutex into a semaphore
Bart Van Assche recently reported a warning to me: <IRQ> [<ffffffff8103d79f>] warn_slowpath_common+0x7f/0xc0 [<ffffffff8103d7fa>] warn_slowpath_null+0x1a/0x20 [<ffffffff814761dd>] mutex_trylock+0x16d/0x180 [<ffffffff813968c9>] netpoll_poll_dev+0x49/0xc30 [<ffffffff8136a2d2>] ? __alloc_skb+0x82/0x2a0 [<ffffffff81397715>] netpoll_send_skb_on_dev+0x265/0x410 [<ffffffff81397c5a>] netpoll_send_udp+0x28a/0x3a0 [<ffffffffa0541843>] ? write_msg+0x53/0x110 [netconsole] [<ffffffffa05418bf>] write_msg+0xcf/0x110 [netconsole] [<ffffffff8103eba1>] call_console_drivers.constprop.17+0xa1/0x1c0 [<ffffffff8103fb76>] console_unlock+0x2d6/0x450 [<ffffffff8104011e>] vprintk_emit+0x1ee/0x510 [<ffffffff8146f9f6>] printk+0x4d/0x4f [<ffffffffa0004f1d>] scsi_print_command+0x7d/0xe0 [scsi_mod] This resulted from my commit ca99ca14c which introduced a mutex_trylock operation in a path that could execute in interrupt context. When mutex debugging is enabled, the above warns the user when we are in fact exectuting in interrupt context interrupt context. After some discussion, It seems that a semaphore is the proper mechanism to use here. While mutexes are defined to be unusable in interrupt context, no such condition exists for semaphores (save for the fact that the non blocking api calls, like up and down_trylock must be used when in irq context). Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Reported-by: Bart Van Assche <bvanassche@acm.org> CC: Bart Van Assche <bvanassche@acm.org> CC: David Miller <davem@davemloft.net> CC: netdev@vger.kernel.org Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/netpoll.c')
-rw-r--r--net/core/netpoll.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 209d84253dd5..a5802a8b652f 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -206,17 +206,17 @@ static void netpoll_poll_dev(struct net_device *dev)
206 * the dev_open/close paths use this to block netpoll activity 206 * the dev_open/close paths use this to block netpoll activity
207 * while changing device state 207 * while changing device state
208 */ 208 */
209 if (!mutex_trylock(&ni->dev_lock)) 209 if (!down_trylock(&ni->dev_lock))
210 return; 210 return;
211 211
212 if (!netif_running(dev)) { 212 if (!netif_running(dev)) {
213 mutex_unlock(&ni->dev_lock); 213 up(&ni->dev_lock);
214 return; 214 return;
215 } 215 }
216 216
217 ops = dev->netdev_ops; 217 ops = dev->netdev_ops;
218 if (!ops->ndo_poll_controller) { 218 if (!ops->ndo_poll_controller) {
219 mutex_unlock(&ni->dev_lock); 219 up(&ni->dev_lock);
220 return; 220 return;
221 } 221 }
222 222
@@ -225,7 +225,7 @@ static void netpoll_poll_dev(struct net_device *dev)
225 225
226 poll_napi(dev); 226 poll_napi(dev);
227 227
228 mutex_unlock(&ni->dev_lock); 228 up(&ni->dev_lock);
229 229
230 if (dev->flags & IFF_SLAVE) { 230 if (dev->flags & IFF_SLAVE) {
231 if (ni) { 231 if (ni) {
@@ -255,7 +255,7 @@ int netpoll_rx_disable(struct net_device *dev)
255 idx = srcu_read_lock(&netpoll_srcu); 255 idx = srcu_read_lock(&netpoll_srcu);
256 ni = srcu_dereference(dev->npinfo, &netpoll_srcu); 256 ni = srcu_dereference(dev->npinfo, &netpoll_srcu);
257 if (ni) 257 if (ni)
258 mutex_lock(&ni->dev_lock); 258 down(&ni->dev_lock);
259 srcu_read_unlock(&netpoll_srcu, idx); 259 srcu_read_unlock(&netpoll_srcu, idx);
260 return 0; 260 return 0;
261} 261}
@@ -267,7 +267,7 @@ void netpoll_rx_enable(struct net_device *dev)
267 rcu_read_lock(); 267 rcu_read_lock();
268 ni = rcu_dereference(dev->npinfo); 268 ni = rcu_dereference(dev->npinfo);
269 if (ni) 269 if (ni)
270 mutex_unlock(&ni->dev_lock); 270 up(&ni->dev_lock);
271 rcu_read_unlock(); 271 rcu_read_unlock();
272} 272}
273EXPORT_SYMBOL(netpoll_rx_enable); 273EXPORT_SYMBOL(netpoll_rx_enable);
@@ -1047,7 +1047,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp)
1047 INIT_LIST_HEAD(&npinfo->rx_np); 1047 INIT_LIST_HEAD(&npinfo->rx_np);
1048 1048
1049 spin_lock_init(&npinfo->rx_lock); 1049 spin_lock_init(&npinfo->rx_lock);
1050 mutex_init(&npinfo->dev_lock); 1050 sema_init(&npinfo->dev_lock, 1);
1051 skb_queue_head_init(&npinfo->neigh_tx); 1051 skb_queue_head_init(&npinfo->neigh_tx);
1052 skb_queue_head_init(&npinfo->txq); 1052 skb_queue_head_init(&npinfo->txq);
1053 INIT_DELAYED_WORK(&npinfo->tx_work, queue_process); 1053 INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);