aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_multicast.c')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index ac33c8f3ea85..aae28620a6e5 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -366,6 +366,21 @@ static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
366 return ret; 366 return ret;
367} 367}
368 368
369void ipoib_mcast_carrier_on_task(struct work_struct *work)
370{
371 struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
372 carrier_on_task);
373
374 /*
375 * Take rtnl_lock to avoid racing with ipoib_stop() and
376 * turning the carrier back on while a device is being
377 * removed.
378 */
379 rtnl_lock();
380 netif_carrier_on(priv->dev);
381 rtnl_unlock();
382}
383
369static int ipoib_mcast_join_complete(int status, 384static int ipoib_mcast_join_complete(int status,
370 struct ib_sa_multicast *multicast) 385 struct ib_sa_multicast *multicast)
371{ 386{
@@ -392,16 +407,12 @@ static int ipoib_mcast_join_complete(int status,
392 &priv->mcast_task, 0); 407 &priv->mcast_task, 0);
393 mutex_unlock(&mcast_mutex); 408 mutex_unlock(&mcast_mutex);
394 409
395 if (mcast == priv->broadcast) { 410 /*
396 /* 411 * Defer carrier on work to ipoib_workqueue to avoid a
397 * Take RTNL lock here to avoid racing with 412 * deadlock on rtnl_lock here.
398 * ipoib_stop() and turning the carrier back 413 */
399 * on while a device is being removed. 414 if (mcast == priv->broadcast)
400 */ 415 queue_work(ipoib_workqueue, &priv->carrier_on_task);
401 rtnl_lock();
402 netif_carrier_on(dev);
403 rtnl_unlock();
404 }
405 416
406 return 0; 417 return 0;
407 } 418 }