summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoni Shoua <monis@Voltaire.COM>2009-09-24 19:01:05 (GMT)
committerRoland Dreier <rolandd@cisco.com>2009-09-24 19:01:05 (GMT)
commit5ee95120841fd623c48d7d971182cf58e3b0c8de (patch)
tree512953a68b5c8e39ae16166aeace89fbcc605123
parent86d710146fb9975f04c505ec78caa43d227c1018 (diff)
downloadlinux-5ee95120841fd623c48d7d971182cf58e3b0c8de.tar.xz
IPoIB: Don't turn on carrier for a non-active port
Multicast joins can succeed even if the IB port is down. This happens when the SM runs on the same port with the requesting port. However, IPoIB calls netif_carrier_on() when the join of the broadcast group succeeds, without caring about the state of the IB port. The result is an IPoIB interface in RUNNING state but without an active IB port to support it. If a bonding interface uses this IPoIB interface as a slave it might not detect that this slave is almost useless and failover functionality will be damaged. The fix checks the state of the IB port in the carrier_task before calling netif_carrier_on(). Adresses: https://bugs.openfabrics.org/show_bug.cgi?id=1726 Signed-off-by: Moni Shoua <monis@voltaire.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 25874fc..8763c1e 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -362,12 +362,19 @@ void ipoib_mcast_carrier_on_task(struct work_struct *work)
{
struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
carrier_on_task);
+ struct ib_port_attr attr;
/*
* Take rtnl_lock to avoid racing with ipoib_stop() and
* turning the carrier back on while a device is being
* removed.
*/
+ if (ib_query_port(priv->ca, priv->port, &attr) ||
+ attr.state != IB_PORT_ACTIVE) {
+ ipoib_dbg(priv, "Keeping carrier off until IB port is active\n");
+ return;
+ }
+
rtnl_lock();
netif_carrier_on(priv->dev);
rtnl_unlock();