IB/mlx4: Add CM paravirtualization

In CM para-virtualization:

1. Incoming requests are steered to the correct vHCA according to the
   embedded GID.
2. Communication IDs on outgoing requests are replaced by a globally
   unique ID, generated by the PPF, since there is no synchronization
   of ID generation between guests (and so these IDs are not
   guaranteed to be globally unique).  The guest's comm ID is stored,
   and is returned to the response MAD when it arrives.

Signed-off-by: Amir Vadai <amirv@mellanox.co.il>
Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Roland Dreier <roland@purestorage.com>
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 29ed3b4..2f13894 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -544,6 +544,10 @@
 					     (struct ib_sa_mad *) mad))
 			return 0;
 		break;
+	case IB_MGMT_CLASS_CM:
+		if (mlx4_ib_demux_cm_handler(ibdev, port, &slave, mad))
+			return 0;
+		break;
 	case IB_MGMT_CLASS_DEVICE_MGMT:
 		if (mad->mad_hdr.method != IB_MGMT_METHOD_GET_RESP)
 			return 0;
@@ -1076,6 +1080,11 @@
 			      (struct ib_sa_mad *) &tunnel->mad))
 			return;
 		break;
+	case IB_MGMT_CLASS_CM:
+		if (mlx4_ib_multiplex_cm_handler(ctx->ib_dev, ctx->port, slave,
+			      (struct ib_mad *) &tunnel->mad))
+			return;
+		break;
 	case IB_MGMT_CLASS_DEVICE_MGMT:
 		if (tunnel->mad.mad_hdr.method != IB_MGMT_METHOD_GET &&
 		    tunnel->mad.mad_hdr.method != IB_MGMT_METHOD_SET)
@@ -1790,6 +1799,7 @@
 
 	dev->sriov.is_going_down = 0;
 	spin_lock_init(&dev->sriov.going_down_lock);
+	mlx4_ib_cm_paravirt_init(dev);
 
 	mlx4_ib_warn(&dev->ib_dev, "multi-function enabled\n");
 
@@ -1818,6 +1828,7 @@
 		mlx4_ib_free_demux_ctx(&dev->sriov.demux[i]);
 		--i;
 	}
+	mlx4_ib_cm_paravirt_clean(dev, -1);
 
 	return err;
 }
@@ -1833,7 +1844,7 @@
 	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
 	dev->sriov.is_going_down = 1;
 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
-	if (mlx4_is_master(dev->dev))
+	if (mlx4_is_master(dev->dev)) {
 		for (i = 0; i < dev->num_ports; i++) {
 			flush_workqueue(dev->sriov.demux[i].ud_wq);
 			mlx4_ib_free_sqp_ctx(dev->sriov.sqps[i]);
@@ -1841,4 +1852,7 @@
 			dev->sriov.sqps[i] = NULL;
 			mlx4_ib_free_demux_ctx(&dev->sriov.demux[i]);
 		}
+
+		mlx4_ib_cm_paravirt_clean(dev, -1);
+	}
 }