IPoIB: Refresh paths instead of flushing them on SM change events
[pandora-kernel.git] / drivers / infiniband / ulp / ipoib / ipoib_ib.c
index 5d50e52..66cafa2 100644 (file)
@@ -902,7 +902,8 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
        return 0;
 }
 
-static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event)
+static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv,
+                               enum ipoib_flush_level level)
 {
        struct ipoib_dev_priv *cpriv;
        struct net_device *dev = priv->dev;
@@ -915,7 +916,7 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event)
         * the parent is down.
         */
        list_for_each_entry(cpriv, &priv->child_intfs, list)
-               __ipoib_ib_dev_flush(cpriv, pkey_event);
+               __ipoib_ib_dev_flush(cpriv, level);
 
        mutex_unlock(&priv->vlan_mutex);
 
@@ -929,7 +930,7 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event)
                return;
        }
 
-       if (pkey_event) {
+       if (level == IPOIB_FLUSH_HEAVY) {
                if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) {
                        clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
                        ipoib_ib_dev_down(dev, 0);
@@ -947,11 +948,15 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event)
                priv->pkey_index = new_index;
        }
 
-       ipoib_dbg(priv, "flushing\n");
+       if (level == IPOIB_FLUSH_LIGHT) {
+               ipoib_mark_paths_invalid(dev);
+               ipoib_mcast_dev_flush(dev);
+       }
 
-       ipoib_ib_dev_down(dev, 0);
+       if (level >= IPOIB_FLUSH_NORMAL)
+               ipoib_ib_dev_down(dev, 0);
 
-       if (pkey_event) {
+       if (level == IPOIB_FLUSH_HEAVY) {
                ipoib_ib_dev_stop(dev, 0);
                ipoib_ib_dev_open(dev);
        }
@@ -961,27 +966,34 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event)
         * we get here, don't bring it back up if it's not configured up
         */
        if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) {
-               ipoib_ib_dev_up(dev);
+               if (level >= IPOIB_FLUSH_NORMAL)
+                       ipoib_ib_dev_up(dev);
                ipoib_mcast_restart_task(&priv->restart_task);
        }
 }
 
-void ipoib_ib_dev_flush(struct work_struct *work)
+void ipoib_ib_dev_flush_light(struct work_struct *work)
+{
+       struct ipoib_dev_priv *priv =
+               container_of(work, struct ipoib_dev_priv, flush_light);
+
+       __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_LIGHT);
+}
+
+void ipoib_ib_dev_flush_normal(struct work_struct *work)
 {
        struct ipoib_dev_priv *priv =
-               container_of(work, struct ipoib_dev_priv, flush_task);
+               container_of(work, struct ipoib_dev_priv, flush_normal);
 
-       ipoib_dbg(priv, "Flushing %s\n", priv->dev->name);
-       __ipoib_ib_dev_flush(priv, 0);
+       __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_NORMAL);
 }
 
-void ipoib_pkey_event(struct work_struct *work)
+void ipoib_ib_dev_flush_heavy(struct work_struct *work)
 {
        struct ipoib_dev_priv *priv =
-               container_of(work, struct ipoib_dev_priv, pkey_event_task);
+               container_of(work, struct ipoib_dev_priv, flush_heavy);
 
-       ipoib_dbg(priv, "Flushing %s and restarting its QP\n", priv->dev->name);
-       __ipoib_ib_dev_flush(priv, 1);
+       __ipoib_ib_dev_flush(priv, IPOIB_FLUSH_HEAVY);
 }
 
 void ipoib_ib_dev_cleanup(struct net_device *dev)