[PATCH 25/30] IB/mlx4: Configure device to work in RoCEv2

2015-02-18 Thread Somnath Kotur
From: Moni Shoua 

Some mlx4 adapters are RoCEv2 capable. To enable this feature some
hardware configuration is required. This is

1. Set port general parameters
2. Configure the outgoing UDP destination port
3. Configure the QP that work with RoCEv2

Signed-off-by: Moni Shoua 
Signed-off-by: Somnath Kotur 
---
 drivers/infiniband/hw/mlx4/main.c |   10 ++-
 drivers/infiniband/hw/mlx4/qp.c   |   39 ++--
 drivers/net/ethernet/mellanox/mlx4/fw.c   |   16 +++-
 drivers/net/ethernet/mellanox/mlx4/mlx4.h |3 +-
 drivers/net/ethernet/mellanox/mlx4/port.c |9 ++-
 drivers/net/ethernet/mellanox/mlx4/qp.c   |   27 
 include/linux/mlx4/device.h   |3 +-
 include/linux/mlx4/qp.h   |   15 +-
 8 files changed, 112 insertions(+), 10 deletions(-)

diff --git a/drivers/infiniband/hw/mlx4/main.c 
b/drivers/infiniband/hw/mlx4/main.c
index ca19d1d..50612b8 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -2154,7 +2154,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
if (mlx4_ib_init_sriov(ibdev))
goto err_mad;
 
-   if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE) {
+   if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE ||
+   dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ROCE_V1_V2) {
if (!iboe->nb.notifier_call) {
iboe->nb.notifier_call = mlx4_ib_netdev_event;
err = register_netdevice_notifier(&iboe->nb);
@@ -2163,6 +2164,13 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
goto err_notif;
}
}
+   if (!mlx4_is_slave(dev) &&
+   dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ROCE_V1_V2) {
+   err = mlx4_config_roce_v2_port(dev, ROCE_V2_UDP_DPORT);
+   if (err) {
+   goto err_notif;
+   }
+   }
}
 
for (j = 0; j < ARRAY_SIZE(mlx4_class_attributes); ++j) {
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 9ab9156..9731c07 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1408,6 +1408,24 @@ static int handle_eth_ud_smac_index(struct mlx4_ib_dev 
*dev,
return 0;
 }
 
+enum {
+   MLX4_QPC_ROCE_MODE_1 = 0,
+   MLX4_QPC_ROCE_MODE_2 = 2,
+   MLX4_QPC_ROCE_MODE_MAX = 0xff
+};
+
+static u8 gid_type_to_qpc(enum ib_gid_type gid_type)
+{
+   switch (gid_type) {
+   case IB_GID_TYPE_IB:
+   return MLX4_QPC_ROCE_MODE_1;
+   case IB_GID_TYPE_ROCE_V2:
+   return MLX4_QPC_ROCE_MODE_2;
+   default:
+   return MLX4_QPC_ROCE_MODE_MAX;
+   }
+}
+
 static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
   const struct ib_qp_attr *attr, int attr_mask,
   enum ib_qp_state cur_state, enum ib_qp_state 
new_state)
@@ -1532,9 +1550,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
u16 vlan = 0x;
u8 smac[ETH_ALEN];
int status = 0;
+   int is_eth = rdma_port_get_link_layer(&dev->ib_dev, qp->port) ==
+   IB_LINK_LAYER_ETHERNET;
 
-   if (rdma_port_get_link_layer(&dev->ib_dev, qp->port) ==
-   IB_LINK_LAYER_ETHERNET) {
+   if (is_eth) {
+   if (mlx4_is_bonded(dev->dev))
+   port_num  = 1;
rcu_read_lock();
status = ib_get_cached_gid(ibqp->device, port_num,
   index, &gid, &gid_attr);
@@ -1551,8 +1572,20 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
  port_num, vlan, smac))
goto out;
 
+   if (is_eth && gid_attr.gid_type == IB_GID_TYPE_ROCE_V2)
+   context->pri_path.hop_limit = IPV6_DEFAULT_HOPLIMIT;
+
optpar |= (MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH |
   MLX4_QP_OPTPAR_SCHED_QUEUE);
+
+   if (is_eth && (cur_state == IB_QPS_INIT && new_state == 
IB_QPS_RTR)) {
+   u8 qpc_roce_mode = gid_type_to_qpc(gid_attr.gid_type);
+
+   if (qpc_roce_mode == MLX4_QPC_ROCE_MODE_MAX)
+   goto out;
+   context->rlkey_roce_mode |= (qpc_roce_mode << 6);
+   }
+
}
 
if (attr_mask & IB_QP_TIMEOUT) {
@@ -1722,7 +1755,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
sqd_event = 0;
 
if (!ibqp->uobject && cur_state == IB_QPS_RESET && new_state == 
IB_QPS_INIT)
-   context->rlkey |= (1 << 4);
+   context->rlkey_roce_mode |= (1 << 4);
 

[PATCH 25/30] IB/mlx4: Configure device to work in RoCEv2

2015-02-18 Thread Somnath Kotur
From: Moni Shoua 

Some mlx4 adapters are RoCEv2 capable. To enable this feature some
hardware configuration is required. This is

1. Set port general parameters
2. Configure the outgoing UDP destination port
3. Configure the QP that work with RoCEv2

Signed-off-by: Moni Shoua 
Signed-off-by: Somnath Kotur 
---
 drivers/infiniband/hw/mlx4/main.c |   10 ++-
 drivers/infiniband/hw/mlx4/qp.c   |   39 ++--
 drivers/net/ethernet/mellanox/mlx4/fw.c   |   16 +++-
 drivers/net/ethernet/mellanox/mlx4/mlx4.h |3 +-
 drivers/net/ethernet/mellanox/mlx4/port.c |9 ++-
 drivers/net/ethernet/mellanox/mlx4/qp.c   |   27 
 include/linux/mlx4/device.h   |3 +-
 include/linux/mlx4/qp.h   |   15 +-
 8 files changed, 112 insertions(+), 10 deletions(-)

diff --git a/drivers/infiniband/hw/mlx4/main.c 
b/drivers/infiniband/hw/mlx4/main.c
index ca19d1d..50612b8 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -2154,7 +2154,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
if (mlx4_ib_init_sriov(ibdev))
goto err_mad;
 
-   if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE) {
+   if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE ||
+   dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ROCE_V1_V2) {
if (!iboe->nb.notifier_call) {
iboe->nb.notifier_call = mlx4_ib_netdev_event;
err = register_netdevice_notifier(&iboe->nb);
@@ -2163,6 +2164,13 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
goto err_notif;
}
}
+   if (!mlx4_is_slave(dev) &&
+   dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ROCE_V1_V2) {
+   err = mlx4_config_roce_v2_port(dev, ROCE_V2_UDP_DPORT);
+   if (err) {
+   goto err_notif;
+   }
+   }
}
 
for (j = 0; j < ARRAY_SIZE(mlx4_class_attributes); ++j) {
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 9ab9156..9731c07 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1408,6 +1408,24 @@ static int handle_eth_ud_smac_index(struct mlx4_ib_dev 
*dev,
return 0;
 }
 
+enum {
+   MLX4_QPC_ROCE_MODE_1 = 0,
+   MLX4_QPC_ROCE_MODE_2 = 2,
+   MLX4_QPC_ROCE_MODE_MAX = 0xff
+};
+
+static u8 gid_type_to_qpc(enum ib_gid_type gid_type)
+{
+   switch (gid_type) {
+   case IB_GID_TYPE_IB:
+   return MLX4_QPC_ROCE_MODE_1;
+   case IB_GID_TYPE_ROCE_V2:
+   return MLX4_QPC_ROCE_MODE_2;
+   default:
+   return MLX4_QPC_ROCE_MODE_MAX;
+   }
+}
+
 static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
   const struct ib_qp_attr *attr, int attr_mask,
   enum ib_qp_state cur_state, enum ib_qp_state 
new_state)
@@ -1532,9 +1550,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
u16 vlan = 0x;
u8 smac[ETH_ALEN];
int status = 0;
+   int is_eth = rdma_port_get_link_layer(&dev->ib_dev, qp->port) ==
+   IB_LINK_LAYER_ETHERNET;
 
-   if (rdma_port_get_link_layer(&dev->ib_dev, qp->port) ==
-   IB_LINK_LAYER_ETHERNET) {
+   if (is_eth) {
+   if (mlx4_is_bonded(dev->dev))
+   port_num  = 1;
rcu_read_lock();
status = ib_get_cached_gid(ibqp->device, port_num,
   index, &gid, &gid_attr);
@@ -1551,8 +1572,20 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
  port_num, vlan, smac))
goto out;
 
+   if (is_eth && gid_attr.gid_type == IB_GID_TYPE_ROCE_V2)
+   context->pri_path.hop_limit = IPV6_DEFAULT_HOPLIMIT;
+
optpar |= (MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH |
   MLX4_QP_OPTPAR_SCHED_QUEUE);
+
+   if (is_eth && (cur_state == IB_QPS_INIT && new_state == 
IB_QPS_RTR)) {
+   u8 qpc_roce_mode = gid_type_to_qpc(gid_attr.gid_type);
+
+   if (qpc_roce_mode == MLX4_QPC_ROCE_MODE_MAX)
+   goto out;
+   context->rlkey_roce_mode |= (qpc_roce_mode << 6);
+   }
+
}
 
if (attr_mask & IB_QP_TIMEOUT) {
@@ -1722,7 +1755,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
sqd_event = 0;
 
if (!ibqp->uobject && cur_state == IB_QPS_RESET && new_state == 
IB_QPS_INIT)
-   context->rlkey |= (1 << 4);
+   context->rlkey_roce_mode |= (1 << 4);