|
@@ -90,6 +90,21 @@ enum {
|
|
|
MLX4_RAW_QP_MSGMAX = 31,
|
|
|
};
|
|
|
|
|
|
+#ifndef ETH_ALEN
|
|
|
+#define ETH_ALEN 6
|
|
|
+#endif
|
|
|
+static inline u64 mlx4_mac_to_u64(u8 *addr)
|
|
|
+{
|
|
|
+ u64 mac = 0;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < ETH_ALEN; i++) {
|
|
|
+ mac <<= 8;
|
|
|
+ mac |= addr[i];
|
|
|
+ }
|
|
|
+ return mac;
|
|
|
+}
|
|
|
+
|
|
|
static const __be32 mlx4_ib_opcode[] = {
|
|
|
[IB_WR_SEND] = cpu_to_be32(MLX4_OPCODE_SEND),
|
|
|
[IB_WR_LSO] = cpu_to_be32(MLX4_OPCODE_LSO),
|
|
@@ -1144,16 +1159,15 @@ static void mlx4_set_sched(struct mlx4_qp_path *path, u8 port)
|
|
|
path->sched_queue = (path->sched_queue & 0xbf) | ((port - 1) << 6);
|
|
|
}
|
|
|
|
|
|
-static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
|
|
|
- struct mlx4_qp_path *path, u8 port)
|
|
|
+static int _mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
|
|
|
+ u64 smac, u16 vlan_tag, struct mlx4_qp_path *path,
|
|
|
+ u8 port)
|
|
|
{
|
|
|
- int err;
|
|
|
int is_eth = rdma_port_get_link_layer(&dev->ib_dev, port) ==
|
|
|
IB_LINK_LAYER_ETHERNET;
|
|
|
- u8 mac[6];
|
|
|
- int is_mcast;
|
|
|
- u16 vlan_tag;
|
|
|
int vidx;
|
|
|
+ int smac_index;
|
|
|
+
|
|
|
|
|
|
path->grh_mylmc = ah->src_path_bits & 0x7f;
|
|
|
path->rlid = cpu_to_be16(ah->dlid);
|
|
@@ -1188,22 +1202,27 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
|
|
|
if (!(ah->ah_flags & IB_AH_GRH))
|
|
|
return -1;
|
|
|
|
|
|
- err = mlx4_ib_resolve_grh(dev, ah, mac, &is_mcast, port);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- memcpy(path->dmac, mac, 6);
|
|
|
+ memcpy(path->dmac, ah->dmac, ETH_ALEN);
|
|
|
path->ackto = MLX4_IB_LINK_TYPE_ETH;
|
|
|
- /* use index 0 into MAC table for IBoE */
|
|
|
- path->grh_mylmc &= 0x80;
|
|
|
+ /* find the index into MAC table for IBoE */
|
|
|
+ if (!is_zero_ether_addr((const u8 *)&smac)) {
|
|
|
+ if (mlx4_find_cached_mac(dev->dev, port, smac,
|
|
|
+ &smac_index))
|
|
|
+ return -ENOENT;
|
|
|
+ } else {
|
|
|
+ smac_index = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ path->grh_mylmc &= 0x80 | smac_index;
|
|
|
|
|
|
- vlan_tag = rdma_get_vlan_id(&dev->iboe.gid_table[port - 1][ah->grh.sgid_index]);
|
|
|
+ path->feup |= MLX4_FEUP_FORCE_ETH_UP;
|
|
|
if (vlan_tag < 0x1000) {
|
|
|
if (mlx4_find_cached_vlan(dev->dev, port, vlan_tag, &vidx))
|
|
|
return -ENOENT;
|
|
|
|
|
|
path->vlan_index = vidx;
|
|
|
path->fl = 1 << 6;
|
|
|
+ path->feup |= MLX4_FVL_FORCE_ETH_VLAN;
|
|
|
}
|
|
|
} else
|
|
|
path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE |
|
|
@@ -1212,6 +1231,28 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_qp_attr *qp,
|
|
|
+ enum ib_qp_attr_mask qp_attr_mask,
|
|
|
+ struct mlx4_qp_path *path, u8 port)
|
|
|
+{
|
|
|
+ return _mlx4_set_path(dev, &qp->ah_attr,
|
|
|
+ mlx4_mac_to_u64((u8 *)qp->smac),
|
|
|
+ (qp_attr_mask & IB_QP_VID) ? qp->vlan_id : 0xffff,
|
|
|
+ path, port);
|
|
|
+}
|
|
|
+
|
|
|
+static int mlx4_set_alt_path(struct mlx4_ib_dev *dev,
|
|
|
+ const struct ib_qp_attr *qp,
|
|
|
+ enum ib_qp_attr_mask qp_attr_mask,
|
|
|
+ struct mlx4_qp_path *path, u8 port)
|
|
|
+{
|
|
|
+ return _mlx4_set_path(dev, &qp->alt_ah_attr,
|
|
|
+ mlx4_mac_to_u64((u8 *)qp->alt_smac),
|
|
|
+ (qp_attr_mask & IB_QP_ALT_VID) ?
|
|
|
+ qp->alt_vlan_id : 0xffff,
|
|
|
+ path, port);
|
|
|
+}
|
|
|
+
|
|
|
static void update_mcg_macs(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
|
|
|
{
|
|
|
struct mlx4_ib_gid_entry *ge, *tmp;
|
|
@@ -1329,7 +1370,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
|
|
}
|
|
|
|
|
|
if (attr_mask & IB_QP_AV) {
|
|
|
- if (mlx4_set_path(dev, &attr->ah_attr, &context->pri_path,
|
|
|
+ if (mlx4_set_path(dev, attr, attr_mask, &context->pri_path,
|
|
|
attr_mask & IB_QP_PORT ?
|
|
|
attr->port_num : qp->port))
|
|
|
goto out;
|
|
@@ -1352,8 +1393,8 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
|
|
dev->dev->caps.pkey_table_len[attr->alt_port_num])
|
|
|
goto out;
|
|
|
|
|
|
- if (mlx4_set_path(dev, &attr->alt_ah_attr, &context->alt_path,
|
|
|
- attr->alt_port_num))
|
|
|
+ if (mlx4_set_alt_path(dev, attr, attr_mask, &context->alt_path,
|
|
|
+ attr->alt_port_num))
|
|
|
goto out;
|
|
|
|
|
|
context->alt_path.pkey_index = attr->alt_pkey_index;
|
|
@@ -1464,6 +1505,17 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
|
|
|
context->pri_path.ackto = (context->pri_path.ackto & 0xf8) |
|
|
|
MLX4_IB_LINK_TYPE_ETH;
|
|
|
|
|
|
+ if (ibqp->qp_type == IB_QPT_UD && (new_state == IB_QPS_RTR)) {
|
|
|
+ int is_eth = rdma_port_get_link_layer(
|
|
|
+ &dev->ib_dev, qp->port) ==
|
|
|
+ IB_LINK_LAYER_ETHERNET;
|
|
|
+ if (is_eth) {
|
|
|
+ context->pri_path.ackto = MLX4_IB_LINK_TYPE_ETH;
|
|
|
+ optpar |= MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
if (cur_state == IB_QPS_RTS && new_state == IB_QPS_SQD &&
|
|
|
attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY && attr->en_sqd_async_notify)
|
|
|
sqd_event = 1;
|
|
@@ -1561,18 +1613,21 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
|
|
struct mlx4_ib_qp *qp = to_mqp(ibqp);
|
|
|
enum ib_qp_state cur_state, new_state;
|
|
|
int err = -EINVAL;
|
|
|
- int p = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
|
|
|
+ int ll;
|
|
|
mutex_lock(&qp->mutex);
|
|
|
|
|
|
cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state;
|
|
|
new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
|
|
|
|
|
|
- if (cur_state == new_state && cur_state == IB_QPS_RESET)
|
|
|
- p = IB_LINK_LAYER_UNSPECIFIED;
|
|
|
+ if (cur_state == new_state && cur_state == IB_QPS_RESET) {
|
|
|
+ ll = IB_LINK_LAYER_UNSPECIFIED;
|
|
|
+ } else {
|
|
|
+ int port = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
|
|
|
+ ll = rdma_port_get_link_layer(&dev->ib_dev, port);
|
|
|
+ }
|
|
|
|
|
|
if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type,
|
|
|
- attr_mask,
|
|
|
- rdma_port_get_link_layer(&dev->ib_dev, p))) {
|
|
|
+ attr_mask, ll)) {
|
|
|
pr_debug("qpn 0x%x: invalid attribute mask specified "
|
|
|
"for transition %d to %d. qp_type %d,"
|
|
|
" attr_mask 0x%x\n",
|
|
@@ -1789,8 +1844,10 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
- vlan = rdma_get_vlan_id(&sgid);
|
|
|
- is_vlan = vlan < 0x1000;
|
|
|
+ if (ah->av.eth.vlan != 0xffff) {
|
|
|
+ vlan = be16_to_cpu(ah->av.eth.vlan) & 0x0fff;
|
|
|
+ is_vlan = 1;
|
|
|
+ }
|
|
|
}
|
|
|
ib_ud_header_init(send_size, !is_eth, is_eth, is_vlan, is_grh, 0, &sqp->ud_header);
|
|
|
|