From b8a1b1ce14252b59b2d5c89de25b54f9bfd4cc5e Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 14 Jan 2009 14:55:41 -0800 Subject: IPoIB: Fix hang in napi_disable() if P_Key is never found After commit fe25c561 ("IPoIB: Don't enable NAPI when it's already enabled"), if an interface is brought up but the corresponding P_Key never appears, then ipoib_stop() will hang in napi_disable(), because ipoib_open() returns before it does napi_enable(). Fix this by changing ipoib_open() to call napi_enable() even if the P_Key isn't present. Reported-by: Yossi Etigin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index dce0443f9d6..0bd2a4ff084 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -106,23 +106,17 @@ int ipoib_open(struct net_device *dev) ipoib_dbg(priv, "bringing up interface\n"); - set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); + if (!test_and_set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) + napi_enable(&priv->napi); if (ipoib_pkey_dev_delay_open(dev)) return 0; - napi_enable(&priv->napi); + if (ipoib_ib_dev_open(dev)) + goto err_disable; - if (ipoib_ib_dev_open(dev)) { - napi_disable(&priv->napi); - return -EINVAL; - } - - if (ipoib_ib_dev_up(dev)) { - ipoib_ib_dev_stop(dev, 1); - napi_disable(&priv->napi); - return -EINVAL; - } + if (ipoib_ib_dev_up(dev)) + goto err_stop; if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { struct ipoib_dev_priv *cpriv; @@ -144,6 +138,15 @@ int ipoib_open(struct net_device *dev) netif_start_queue(dev); return 0; + +err_stop: + ipoib_ib_dev_stop(dev, 1); + +err_disable: + napi_disable(&priv->napi); + clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); + + return -EINVAL; } static int ipoib_stop(struct net_device *dev) -- cgit v1.2.3