IB/mlx4: Add support for blocking multicast loopback packets
authorRon Livne <ronli@voltaire.com>
Tue, 15 Jul 2008 06:48:48 +0000 (23:48 -0700)
committerRoland Dreier <rolandd@cisco.com>
Tue, 15 Jul 2008 06:48:48 +0000 (23:48 -0700)
Add support for handling the IB_QP_CREATE_MULTICAST_BLOCK_LOOPBACK
flag by using the per-multicast group loopback blocking feature of
mlx4 hardware.

Signed-off-by: Ron Livne <ronli@voltaire.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/mlx4_ib.h
drivers/infiniband/hw/mlx4/qp.c
drivers/net/mlx4/mcg.c
include/linux/mlx4/device.h

index 4d61e32..bcf5064 100644 (file)
@@ -90,7 +90,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
        props->device_cap_flags    = IB_DEVICE_CHANGE_PHY_PORT |
                IB_DEVICE_PORT_ACTIVE_EVENT             |
                IB_DEVICE_SYS_IMAGE_GUID                |
-               IB_DEVICE_RC_RNR_NAK_GEN;
+               IB_DEVICE_RC_RNR_NAK_GEN                |
+               IB_DEVICE_BLOCK_MULTICAST_LOOPBACK;
        if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR)
                props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;
        if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR)
@@ -437,7 +438,9 @@ static int mlx4_ib_dealloc_pd(struct ib_pd *pd)
 static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 {
        return mlx4_multicast_attach(to_mdev(ibqp->device)->dev,
-                                    &to_mqp(ibqp)->mqp, gid->raw);
+                                    &to_mqp(ibqp)->mqp, gid->raw,
+                                    !!(to_mqp(ibqp)->flags &
+                                       MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK));
 }
 
 static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
index 5cf9947..c4cf5b6 100644 (file)
@@ -101,7 +101,8 @@ struct mlx4_ib_wq {
 };
 
 enum mlx4_ib_qp_flags {
-       MLX4_IB_QP_LSO          = 1 << 0
+       MLX4_IB_QP_LSO                          = 1 << 0,
+       MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK     = 1 << 1,
 };
 
 struct mlx4_ib_qp {
index 44bbd6c..91590e7 100644 (file)
@@ -511,6 +511,9 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
        } else {
                qp->sq_no_prefetch = 0;
 
+               if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK)
+                       qp->flags |= MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK;
+
                if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO)
                        qp->flags |= MLX4_IB_QP_LSO;
 
@@ -684,10 +687,15 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
        struct mlx4_ib_qp *qp;
        int err;
 
-       /* We only support LSO, and only for kernel UD QPs. */
-       if (init_attr->create_flags & ~IB_QP_CREATE_IPOIB_UD_LSO)
+       /*
+        * We only support LSO and multicast loopback blocking, and
+        * only for kernel UD QPs.
+        */
+       if (init_attr->create_flags & ~(IB_QP_CREATE_IPOIB_UD_LSO |
+                                       IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK))
                return ERR_PTR(-EINVAL);
-       if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO &&
+
+       if (init_attr->create_flags &&
            (pd->uobject || init_attr->qp_type != IB_QPT_UD))
                return ERR_PTR(-EINVAL);
 
@@ -1844,6 +1852,13 @@ done:
 
        qp_init_attr->cap            = qp_attr->cap;
 
+       qp_init_attr->create_flags = 0;
+       if (qp->flags & MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK)
+               qp_init_attr->create_flags |= IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK;
+
+       if (qp->flags & MLX4_IB_QP_LSO)
+               qp_init_attr->create_flags |= IB_QP_CREATE_IPOIB_UD_LSO;
+
 out:
        mutex_unlock(&qp->mutex);
        return err;
index 57f7f1f..b4b5787 100644 (file)
@@ -38,6 +38,9 @@
 
 #include "mlx4.h"
 
+#define MGM_QPN_MASK       0x00FFFFFF
+#define MGM_BLCK_LB_BIT    30
+
 struct mlx4_mgm {
        __be32                  next_gid_index;
        __be32                  members_count;
@@ -153,7 +156,8 @@ static int find_mgm(struct mlx4_dev *dev,
        return err;
 }
 
-int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
+int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+                         int block_mcast_loopback)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
        struct mlx4_cmd_mailbox *mailbox;
@@ -202,13 +206,18 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
        }
 
        for (i = 0; i < members_count; ++i)
-               if (mgm->qp[i] == cpu_to_be32(qp->qpn)) {
+               if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn) {
                        mlx4_dbg(dev, "QP %06x already a member of MGM\n", qp->qpn);
                        err = 0;
                        goto out;
                }
 
-       mgm->qp[members_count++] = cpu_to_be32(qp->qpn);
+       if (block_mcast_loopback)
+               mgm->qp[members_count++] = cpu_to_be32((qp->qpn & MGM_QPN_MASK) |
+                                                      (1 << MGM_BLCK_LB_BIT));
+       else
+               mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK);
+
        mgm->members_count       = cpu_to_be32(members_count);
 
        err = mlx4_WRITE_MCG(dev, index, mailbox);
@@ -283,7 +292,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
 
        members_count = be32_to_cpu(mgm->members_count);
        for (loc = -1, i = 0; i < members_count; ++i)
-               if (mgm->qp[i] == cpu_to_be32(qp->qpn))
+               if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn)
                        loc = i;
 
        if (loc == -1) {
index a744383..81b3dd5 100644 (file)
@@ -398,7 +398,8 @@ int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_waterm
 int mlx4_INIT_PORT(struct mlx4_dev *dev, int port);
 int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port);
 
-int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]);
+int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+                         int block_mcast_loopback);
 int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]);
 
 int mlx4_map_phys_fmr(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u64 *page_list,