Add RAW ETH QP support for Mellanox adapters.

Signed-off-by: Aleksey Senin <[email protected]>
---
 drivers/infiniband/hw/mlx4/main.c |   13 +++++++++----
 drivers/infiniband/hw/mlx4/qp.c   |   25 +++++++++++++++++++++----
 drivers/net/mlx4/mcg.c            |   22 +++++++++++++---------
 include/linux/mlx4/device.h       |    7 +++++--
 4 files changed, 48 insertions(+), 19 deletions(-)

diff --git a/drivers/infiniband/hw/mlx4/main.c 
b/drivers/infiniband/hw/mlx4/main.c
index c146b84..6841dc7 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -684,7 +684,9 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union 
ib_gid *gid, u16 lid)
        struct mlx4_ib_qp *mqp = to_mqp(ibqp);
 
        err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, 
!!(mqp->flags &
-                                   MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK));
+                                   MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK),
+                                       (ibqp->qp_type == IB_QPT_RAW_ETH) ?
+                                       MLX4_PROT_EN : MLX4_PROT_IB);
        if (err)
                return err;
 
@@ -695,7 +697,9 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union 
ib_gid *gid, u16 lid)
        return 0;
 
 err_add:
-       mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw);
+       mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw,
+                                       (ibqp->qp_type == IB_QPT_RAW_ETH) ?
+                                       MLX4_PROT_EN : MLX4_PROT_IB);
        return err;
 }
 
@@ -724,8 +728,9 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union 
ib_gid *gid, u16 lid)
        struct net_device *ndev;
        struct gid_entry *ge;
 
-       err = mlx4_multicast_detach(mdev->dev,
-                                   &mqp->mqp, gid->raw);
+       err = mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw,
+                                       (ibqp->qp_type == IB_QPT_RAW_ETH) ?
+                                       MLX4_PROT_EN : MLX4_PROT_IB);
        if (err)
                return err;
 
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 422d367..b6b484d 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -811,6 +811,7 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
        case IB_QPT_RC:
        case IB_QPT_UC:
        case IB_QPT_UD:
+       case IB_QPT_RAW_ETH:
        {
                qp = kzalloc(sizeof *qp, GFP_KERNEL);
                if (!qp)
@@ -902,6 +903,7 @@ static int to_mlx4_st(enum ib_qp_type type)
        case IB_QPT_RAW_ETY:
        case IB_QPT_SMI:
        case IB_QPT_GSI:        return MLX4_QP_ST_MLX;
+       case IB_QPT_RAW_ETH:    return MLX4_QP_ST_MLX;
        default:                return -1;
        }
 }
@@ -1064,8 +1066,9 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
                        break;
                }
        }
-
-       if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI ||
+       if (ibqp->qp_type == IB_QPT_RAW_ETH)
+               context->mtu_msgmax = 0xff;
+       else if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI ||
            ibqp->qp_type == IB_QPT_RAW_ETY)
                context->mtu_msgmax = (IB_MTU_4096 << 5) | 11;
        else if (ibqp->qp_type == IB_QPT_UD) {
@@ -1237,12 +1240,16 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
        if (cur_state == IB_QPS_INIT &&
            new_state == IB_QPS_RTR  &&
            (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI ||
-            ibqp->qp_type == IB_QPT_UD || ibqp->qp_type == IB_QPT_RAW_ETY)) {
+            ibqp->qp_type == IB_QPT_UD || ibqp->qp_type == IB_QPT_RAW_ETY ||
+               ibqp->qp_type == IB_QPT_RAW_ETH)) {
                context->pri_path.sched_queue = (qp->port - 1) << 6;
                if (is_qp0(dev, qp))
                        context->pri_path.sched_queue |= 
MLX4_IB_DEFAULT_QP0_SCHED_QUEUE;
                else
                        context->pri_path.sched_queue |= 
MLX4_IB_DEFAULT_SCHED_QUEUE;
+
+               /* Default counter for non-RC QPs */
+               context->pri_path.counter_index = 0xff;
        }
 
        if (cur_state == IB_QPS_RTS && new_state == IB_QPS_SQD  &&
@@ -1356,7 +1363,7 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct 
ib_qp_attr *attr,
                goto out;
        }
 
-       if ((attr_mask & IB_QP_PORT) &&
+       if ((attr_mask & IB_QP_PORT) && (ibqp->qp_type != IB_QPT_RAW_ETH) &&
            (attr->port_num == 0 || attr->port_num > dev->num_ports)) {
                mlx4_ib_dbg("qpn 0x%x: invalid port number (%d) specified "
                            "for transition %d to %d. qp_type %d",
@@ -1365,6 +1372,16 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct 
ib_qp_attr *attr,
                goto out;
        }
 
+       if ((attr_mask & IB_QP_PORT) && (ibqp->qp_type == IB_QPT_RAW_ETH) &&
+               (rdma_port_link_layer(&dev->ib_dev, attr->port_num)
+                               != IB_LINK_LAYER_ETHERNET)) {
+               mlx4_ib_dbg("qpn 0x%x: invalid port (%d) specified (not RDMAoE)"
+                           "for transition %d to %d. qp_type %d",
+                           ibqp->qp_num, attr->port_num, cur_state,
+                           new_state, ibqp->qp_type);
+               goto out;
+       }
+
        if (attr_mask & IB_QP_PKEY_INDEX) {
                int p = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
                if (attr->pkey_index >= dev->dev->caps.pkey_table_len[p]) {
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
index 61c1e40..10a3eb5 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -36,6 +36,7 @@
 #include <linux/slab.h>
 
 #include <linux/mlx4/cmd.h>
+#include <linux/mlx4/driver.h>
 
 #include "mlx4.h"
 
@@ -97,7 +98,8 @@ static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct 
mlx4_cmd_mailbox *mailbox
  * entry in hash chain and *mgm holds end of hash chain.
  */
 static int find_mgm(struct mlx4_dev *dev,
-                   u8 *gid, struct mlx4_cmd_mailbox *mgm_mailbox,
+                   u8 *gid, enum mlx4_prot prot,
+                   struct mlx4_cmd_mailbox *mgm_mailbox,
                    u16 *hash, int *prev, int *index)
 {
        struct mlx4_cmd_mailbox *mailbox;
@@ -146,8 +148,9 @@ static int find_mgm(struct mlx4_dev *dev,
                        return err;
                }
 
-               if (!memcmp(mgm->gid, gid, 16))
-                       return err;
+               if (!memcmp(mgm->gid, gid, 16) &&
+                               (prot == be32_to_cpu(mgm->members_count) >> 30))
+                               return err;
 
                *prev = *index;
                *index = be32_to_cpu(mgm->next_gid_index) >> 6;
@@ -158,7 +161,7 @@ static int find_mgm(struct mlx4_dev *dev,
 }
 
 int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
-                         int block_mcast_loopback)
+                         int block_mcast_loopback, enum mlx4_prot prot)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
        struct mlx4_cmd_mailbox *mailbox;
@@ -177,7 +180,7 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct 
mlx4_qp *qp, u8 gid[16],
 
        mutex_lock(&priv->mcg_table.mutex);
 
-       err = find_mgm(dev, gid, mailbox, &hash, &prev, &index);
+       err = find_mgm(dev, gid, prot, mailbox, &hash, &prev, &index);
        if (err)
                goto out;
 
@@ -216,7 +219,7 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct 
mlx4_qp *qp, u8 gid[16],
        mgm->qp[members_count++] = cpu_to_be32((qp->qpn & MGM_QPN_MASK) |
                                               (!!mlx4_blck_lb << 
MGM_BLCK_LB_BIT));
 
-       mgm->members_count       = cpu_to_be32(members_count);
+       mgm->members_count = cpu_to_be32(members_count | ((u32) prot << 30));
 
        err = mlx4_WRITE_MCG(dev, index, mailbox);
        if (err)
@@ -251,7 +254,8 @@ out:
 }
 EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
 
-int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
+int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+                                               enum mlx4_prot prot)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
        struct mlx4_cmd_mailbox *mailbox;
@@ -269,7 +273,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct 
mlx4_qp *qp, u8 gid[16])
 
        mutex_lock(&priv->mcg_table.mutex);
 
-       err = find_mgm(dev, gid, mailbox, &hash, &prev, &index);
+       err = find_mgm(dev, gid, prot, mailbox, &hash, &prev, &index);
        if (err)
                goto out;
 
@@ -300,7 +304,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct 
mlx4_qp *qp, u8 gid[16])
        }
 
 
-       mgm->members_count = cpu_to_be32(--members_count);
+       mgm->members_count = cpu_to_be32(--members_count | ((u32) prot << 30));
        mgm->qp[loc]       = mgm->qp[i - 1];
        mgm->qp[i - 1]     = 0;
 
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 782a9b5..9ca1326 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -39,6 +39,8 @@
 
 #include <asm/atomic.h>
 
+#include <linux/mlx4/driver.h>
+
 enum {
        MLX4_FLAG_MSI_X         = 1 << 0,
        MLX4_FLAG_OLD_PORT_CMDS = 1 << 1,
@@ -561,8 +563,9 @@ 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 block_mcast_loopback);
-int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 
gid[16]);
+                         int block_mcast_loopback, enum mlx4_prot prot);
+int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+                               enum mlx4_prot prot);
 
 int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index);
 void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index);
-- 
1.6.5.2


_______________________________________________
ewg mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/ewg

Reply via email to