diff options
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib.h | 2 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 1 | ||||
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 31 |
3 files changed, 24 insertions, 10 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index b0ffc9abe8c0..05eb41b8ab63 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
| @@ -293,6 +293,7 @@ struct ipoib_dev_priv { | |||
| 293 | 293 | ||
| 294 | struct delayed_work pkey_poll_task; | 294 | struct delayed_work pkey_poll_task; |
| 295 | struct delayed_work mcast_task; | 295 | struct delayed_work mcast_task; |
| 296 | struct work_struct carrier_on_task; | ||
| 296 | struct work_struct flush_light; | 297 | struct work_struct flush_light; |
| 297 | struct work_struct flush_normal; | 298 | struct work_struct flush_normal; |
| 298 | struct work_struct flush_heavy; | 299 | struct work_struct flush_heavy; |
| @@ -464,6 +465,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port); | |||
| 464 | void ipoib_dev_cleanup(struct net_device *dev); | 465 | void ipoib_dev_cleanup(struct net_device *dev); |
| 465 | 466 | ||
| 466 | void ipoib_mcast_join_task(struct work_struct *work); | 467 | void ipoib_mcast_join_task(struct work_struct *work); |
| 468 | void ipoib_mcast_carrier_on_task(struct work_struct *work); | ||
| 467 | void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb); | 469 | void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb); |
| 468 | 470 | ||
| 469 | void ipoib_mcast_restart_task(struct work_struct *work); | 471 | void ipoib_mcast_restart_task(struct work_struct *work); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 7e9e218738fa..1b1df5cc4113 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
| @@ -1075,6 +1075,7 @@ static void ipoib_setup(struct net_device *dev) | |||
| 1075 | 1075 | ||
| 1076 | INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll); | 1076 | INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll); |
| 1077 | INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); | 1077 | INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); |
| 1078 | INIT_WORK(&priv->carrier_on_task, ipoib_mcast_carrier_on_task); | ||
| 1078 | INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light); | 1079 | INIT_WORK(&priv->flush_light, ipoib_ib_dev_flush_light); |
| 1079 | INIT_WORK(&priv->flush_normal, ipoib_ib_dev_flush_normal); | 1080 | INIT_WORK(&priv->flush_normal, ipoib_ib_dev_flush_normal); |
| 1080 | INIT_WORK(&priv->flush_heavy, ipoib_ib_dev_flush_heavy); | 1081 | INIT_WORK(&priv->flush_heavy, ipoib_ib_dev_flush_heavy); |
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 | ||
| 369 | void 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 | |||
| 369 | static int ipoib_mcast_join_complete(int status, | 384 | static 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 | } |
