aboutsummaryrefslogtreecommitdiff
path: root/net/core/netpoll.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2013-04-30 05:35:05 +0000
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 209d84253dd..a5802a8b652 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -206,17 +206,17 @@ static void netpoll_poll_dev(struct net_device *dev)
* the dev_open/close paths use this to block netpoll activity
* while changing device state
*/
- if (!mutex_trylock(&ni->dev_lock))
+ if (!down_trylock(&ni->dev_lock))
return;
if (!netif_running(dev)) {
- mutex_unlock(&ni->dev_lock);
+ up(&ni->dev_lock);
return;
}
ops = dev->netdev_ops;
if (!ops->ndo_poll_controller) {
- mutex_unlock(&ni->dev_lock);
+ up(&ni->dev_lock);
return;
}
@@ -225,7 +225,7 @@ static void netpoll_poll_dev(struct net_device *dev)
poll_napi(dev);
- mutex_unlock(&ni->dev_lock);
+ up(&ni->dev_lock);
if (dev->flags & IFF_SLAVE) {
if (ni) {
@@ -255,7 +255,7 @@ int netpoll_rx_disable(struct net_device *dev)
idx = srcu_read_lock(&netpoll_srcu);
ni = srcu_dereference(dev->npinfo, &netpoll_srcu);
if (ni)
- mutex_lock(&ni->dev_lock);
+ down(&ni->dev_lock);
srcu_read_unlock(&netpoll_srcu, idx);
return 0;
}
@@ -267,7 +267,7 @@ void netpoll_rx_enable(struct net_device *dev)
rcu_read_lock();
ni = rcu_dereference(dev->npinfo);
if (ni)
- mutex_unlock(&ni->dev_lock);
+ up(&ni->dev_lock);
rcu_read_unlock();
}
EXPORT_SYMBOL(netpoll_rx_enable);
@@ -1047,7 +1047,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp)
INIT_LIST_HEAD(&npinfo->rx_np);
spin_lock_init(&npinfo->rx_lock);
- mutex_init(&npinfo->dev_lock);
+ sema_init(&npinfo->dev_lock, 1);
skb_queue_head_init(&npinfo->neigh_tx);
skb_queue_head_init(&npinfo->txq);
INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);