|
@@ -41,6 +41,9 @@
|
|
#include <linux/export.h>
|
|
#include <linux/export.h>
|
|
#include <linux/string.h>
|
|
#include <linux/string.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/slab.h>
|
|
|
|
+#include <linux/in.h>
|
|
|
|
+#include <linux/in6.h>
|
|
|
|
+#include <net/addrconf.h>
|
|
|
|
|
|
#include <rdma/ib_verbs.h>
|
|
#include <rdma/ib_verbs.h>
|
|
#include <rdma/ib_cache.h>
|
|
#include <rdma/ib_cache.h>
|
|
@@ -308,6 +311,35 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(ib_create_ah);
|
|
EXPORT_SYMBOL(ib_create_ah);
|
|
|
|
|
|
|
|
+struct find_gid_index_context {
|
|
|
|
+ u16 vlan_id;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static bool find_gid_index(const union ib_gid *gid,
|
|
|
|
+ const struct ib_gid_attr *gid_attr,
|
|
|
|
+ void *context)
|
|
|
|
+{
|
|
|
|
+ struct find_gid_index_context *ctx =
|
|
|
|
+ (struct find_gid_index_context *)context;
|
|
|
|
+
|
|
|
|
+ if ((!!(ctx->vlan_id != 0xffff) == !is_vlan_dev(gid_attr->ndev)) ||
|
|
|
|
+ (is_vlan_dev(gid_attr->ndev) &&
|
|
|
|
+ vlan_dev_vlan_id(gid_attr->ndev) != ctx->vlan_id))
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int get_sgid_index_from_eth(struct ib_device *device, u8 port_num,
|
|
|
|
+ u16 vlan_id, const union ib_gid *sgid,
|
|
|
|
+ u16 *gid_index)
|
|
|
|
+{
|
|
|
|
+ struct find_gid_index_context context = {.vlan_id = vlan_id};
|
|
|
|
+
|
|
|
|
+ return ib_find_gid_by_filter(device, sgid, port_num, find_gid_index,
|
|
|
|
+ &context, gid_index);
|
|
|
|
+}
|
|
|
|
+
|
|
int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
|
|
int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
|
|
const struct ib_wc *wc, const struct ib_grh *grh,
|
|
const struct ib_wc *wc, const struct ib_grh *grh,
|
|
struct ib_ah_attr *ah_attr)
|
|
struct ib_ah_attr *ah_attr)
|
|
@@ -318,21 +350,30 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
|
|
|
|
|
|
memset(ah_attr, 0, sizeof *ah_attr);
|
|
memset(ah_attr, 0, sizeof *ah_attr);
|
|
if (rdma_cap_eth_ah(device, port_num)) {
|
|
if (rdma_cap_eth_ah(device, port_num)) {
|
|
|
|
+ u16 vlan_id = wc->wc_flags & IB_WC_WITH_VLAN ?
|
|
|
|
+ wc->vlan_id : 0xffff;
|
|
|
|
+
|
|
if (!(wc->wc_flags & IB_WC_GRH))
|
|
if (!(wc->wc_flags & IB_WC_GRH))
|
|
return -EPROTOTYPE;
|
|
return -EPROTOTYPE;
|
|
|
|
|
|
- if (wc->wc_flags & IB_WC_WITH_SMAC &&
|
|
|
|
- wc->wc_flags & IB_WC_WITH_VLAN) {
|
|
|
|
- memcpy(ah_attr->dmac, wc->smac, ETH_ALEN);
|
|
|
|
- ah_attr->vlan_id = wc->vlan_id;
|
|
|
|
- } else {
|
|
|
|
|
|
+ if (!(wc->wc_flags & IB_WC_WITH_SMAC) ||
|
|
|
|
+ !(wc->wc_flags & IB_WC_WITH_VLAN)) {
|
|
ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid,
|
|
ret = rdma_addr_find_dmac_by_grh(&grh->dgid, &grh->sgid,
|
|
- ah_attr->dmac, &ah_attr->vlan_id);
|
|
|
|
|
|
+ ah_attr->dmac,
|
|
|
|
+ wc->wc_flags & IB_WC_WITH_VLAN ?
|
|
|
|
+ NULL : &vlan_id,
|
|
|
|
+ 0);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
- } else {
|
|
|
|
- ah_attr->vlan_id = 0xffff;
|
|
|
|
|
|
+
|
|
|
|
+ ret = get_sgid_index_from_eth(device, port_num, vlan_id,
|
|
|
|
+ &grh->dgid, &gid_index);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
|
|
+ if (wc->wc_flags & IB_WC_WITH_SMAC)
|
|
|
|
+ memcpy(ah_attr->dmac, wc->smac, ETH_ALEN);
|
|
}
|
|
}
|
|
|
|
|
|
ah_attr->dlid = wc->slid;
|
|
ah_attr->dlid = wc->slid;
|
|
@@ -344,10 +385,13 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
|
|
ah_attr->ah_flags = IB_AH_GRH;
|
|
ah_attr->ah_flags = IB_AH_GRH;
|
|
ah_attr->grh.dgid = grh->sgid;
|
|
ah_attr->grh.dgid = grh->sgid;
|
|
|
|
|
|
- ret = ib_find_cached_gid(device, &grh->dgid,
|
|
|
|
- NULL, &port_num, &gid_index);
|
|
|
|
- if (ret)
|
|
|
|
- return ret;
|
|
|
|
|
|
+ if (!rdma_cap_eth_ah(device, port_num)) {
|
|
|
|
+ ret = ib_find_cached_gid_by_port(device, &grh->dgid,
|
|
|
|
+ port_num, NULL,
|
|
|
|
+ &gid_index);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
|
|
ah_attr->grh.sgid_index = (u8) gid_index;
|
|
ah_attr->grh.sgid_index = (u8) gid_index;
|
|
flow_class = be32_to_cpu(grh->version_tclass_flow);
|
|
flow_class = be32_to_cpu(grh->version_tclass_flow);
|
|
@@ -617,9 +661,7 @@ EXPORT_SYMBOL(ib_create_qp);
|
|
static const struct {
|
|
static const struct {
|
|
int valid;
|
|
int valid;
|
|
enum ib_qp_attr_mask req_param[IB_QPT_MAX];
|
|
enum ib_qp_attr_mask req_param[IB_QPT_MAX];
|
|
- enum ib_qp_attr_mask req_param_add_eth[IB_QPT_MAX];
|
|
|
|
enum ib_qp_attr_mask opt_param[IB_QPT_MAX];
|
|
enum ib_qp_attr_mask opt_param[IB_QPT_MAX];
|
|
- enum ib_qp_attr_mask opt_param_add_eth[IB_QPT_MAX];
|
|
|
|
} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
|
|
} qp_state_table[IB_QPS_ERR + 1][IB_QPS_ERR + 1] = {
|
|
[IB_QPS_RESET] = {
|
|
[IB_QPS_RESET] = {
|
|
[IB_QPS_RESET] = { .valid = 1 },
|
|
[IB_QPS_RESET] = { .valid = 1 },
|
|
@@ -700,12 +742,6 @@ static const struct {
|
|
IB_QP_MAX_DEST_RD_ATOMIC |
|
|
IB_QP_MAX_DEST_RD_ATOMIC |
|
|
IB_QP_MIN_RNR_TIMER),
|
|
IB_QP_MIN_RNR_TIMER),
|
|
},
|
|
},
|
|
- .req_param_add_eth = {
|
|
|
|
- [IB_QPT_RC] = (IB_QP_SMAC),
|
|
|
|
- [IB_QPT_UC] = (IB_QP_SMAC),
|
|
|
|
- [IB_QPT_XRC_INI] = (IB_QP_SMAC),
|
|
|
|
- [IB_QPT_XRC_TGT] = (IB_QP_SMAC)
|
|
|
|
- },
|
|
|
|
.opt_param = {
|
|
.opt_param = {
|
|
[IB_QPT_UD] = (IB_QP_PKEY_INDEX |
|
|
[IB_QPT_UD] = (IB_QP_PKEY_INDEX |
|
|
IB_QP_QKEY),
|
|
IB_QP_QKEY),
|
|
@@ -726,21 +762,7 @@ static const struct {
|
|
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
|
|
[IB_QPT_GSI] = (IB_QP_PKEY_INDEX |
|
|
IB_QP_QKEY),
|
|
IB_QP_QKEY),
|
|
},
|
|
},
|
|
- .opt_param_add_eth = {
|
|
|
|
- [IB_QPT_RC] = (IB_QP_ALT_SMAC |
|
|
|
|
- IB_QP_VID |
|
|
|
|
- IB_QP_ALT_VID),
|
|
|
|
- [IB_QPT_UC] = (IB_QP_ALT_SMAC |
|
|
|
|
- IB_QP_VID |
|
|
|
|
- IB_QP_ALT_VID),
|
|
|
|
- [IB_QPT_XRC_INI] = (IB_QP_ALT_SMAC |
|
|
|
|
- IB_QP_VID |
|
|
|
|
- IB_QP_ALT_VID),
|
|
|
|
- [IB_QPT_XRC_TGT] = (IB_QP_ALT_SMAC |
|
|
|
|
- IB_QP_VID |
|
|
|
|
- IB_QP_ALT_VID)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ },
|
|
},
|
|
},
|
|
[IB_QPS_RTR] = {
|
|
[IB_QPS_RTR] = {
|
|
[IB_QPS_RESET] = { .valid = 1 },
|
|
[IB_QPS_RESET] = { .valid = 1 },
|
|
@@ -962,13 +984,6 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
|
|
req_param = qp_state_table[cur_state][next_state].req_param[type];
|
|
req_param = qp_state_table[cur_state][next_state].req_param[type];
|
|
opt_param = qp_state_table[cur_state][next_state].opt_param[type];
|
|
opt_param = qp_state_table[cur_state][next_state].opt_param[type];
|
|
|
|
|
|
- if (ll == IB_LINK_LAYER_ETHERNET) {
|
|
|
|
- req_param |= qp_state_table[cur_state][next_state].
|
|
|
|
- req_param_add_eth[type];
|
|
|
|
- opt_param |= qp_state_table[cur_state][next_state].
|
|
|
|
- opt_param_add_eth[type];
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if ((mask & req_param) != req_param)
|
|
if ((mask & req_param) != req_param)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -979,41 +994,52 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state,
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(ib_modify_qp_is_ok);
|
|
EXPORT_SYMBOL(ib_modify_qp_is_ok);
|
|
|
|
|
|
-int ib_resolve_eth_l2_attrs(struct ib_qp *qp,
|
|
|
|
- struct ib_qp_attr *qp_attr, int *qp_attr_mask)
|
|
|
|
|
|
+int ib_resolve_eth_dmac(struct ib_qp *qp,
|
|
|
|
+ struct ib_qp_attr *qp_attr, int *qp_attr_mask)
|
|
{
|
|
{
|
|
int ret = 0;
|
|
int ret = 0;
|
|
- union ib_gid sgid;
|
|
|
|
|
|
|
|
- if ((*qp_attr_mask & IB_QP_AV) &&
|
|
|
|
- (rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num))) {
|
|
|
|
- ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num,
|
|
|
|
- qp_attr->ah_attr.grh.sgid_index, &sgid,
|
|
|
|
- NULL);
|
|
|
|
- if (ret)
|
|
|
|
- goto out;
|
|
|
|
|
|
+ if (*qp_attr_mask & IB_QP_AV) {
|
|
|
|
+ if (qp_attr->ah_attr.port_num < rdma_start_port(qp->device) ||
|
|
|
|
+ qp_attr->ah_attr.port_num > rdma_end_port(qp->device))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ if (!rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num))
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) {
|
|
if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) {
|
|
- rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw, qp_attr->ah_attr.dmac);
|
|
|
|
- rdma_get_ll_mac((struct in6_addr *)sgid.raw, qp_attr->smac);
|
|
|
|
- if (!(*qp_attr_mask & IB_QP_VID))
|
|
|
|
- qp_attr->vlan_id = rdma_get_vlan_id(&sgid);
|
|
|
|
|
|
+ rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw,
|
|
|
|
+ qp_attr->ah_attr.dmac);
|
|
} else {
|
|
} else {
|
|
- ret = rdma_addr_find_dmac_by_grh(&sgid, &qp_attr->ah_attr.grh.dgid,
|
|
|
|
- qp_attr->ah_attr.dmac, &qp_attr->vlan_id);
|
|
|
|
- if (ret)
|
|
|
|
- goto out;
|
|
|
|
- ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr->smac, NULL);
|
|
|
|
- if (ret)
|
|
|
|
|
|
+ union ib_gid sgid;
|
|
|
|
+ struct ib_gid_attr sgid_attr;
|
|
|
|
+ int ifindex;
|
|
|
|
+
|
|
|
|
+ ret = ib_query_gid(qp->device,
|
|
|
|
+ qp_attr->ah_attr.port_num,
|
|
|
|
+ qp_attr->ah_attr.grh.sgid_index,
|
|
|
|
+ &sgid, &sgid_attr);
|
|
|
|
+
|
|
|
|
+ if (ret || !sgid_attr.ndev) {
|
|
|
|
+ if (!ret)
|
|
|
|
+ ret = -ENXIO;
|
|
goto out;
|
|
goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ifindex = sgid_attr.ndev->ifindex;
|
|
|
|
+
|
|
|
|
+ ret = rdma_addr_find_dmac_by_grh(&sgid,
|
|
|
|
+ &qp_attr->ah_attr.grh.dgid,
|
|
|
|
+ qp_attr->ah_attr.dmac,
|
|
|
|
+ NULL, ifindex);
|
|
|
|
+
|
|
|
|
+ dev_put(sgid_attr.ndev);
|
|
}
|
|
}
|
|
- *qp_attr_mask |= IB_QP_SMAC;
|
|
|
|
- if (qp_attr->vlan_id < 0xFFFF)
|
|
|
|
- *qp_attr_mask |= IB_QP_VID;
|
|
|
|
}
|
|
}
|
|
out:
|
|
out:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
-EXPORT_SYMBOL(ib_resolve_eth_l2_attrs);
|
|
|
|
|
|
+EXPORT_SYMBOL(ib_resolve_eth_dmac);
|
|
|
|
|
|
|
|
|
|
int ib_modify_qp(struct ib_qp *qp,
|
|
int ib_modify_qp(struct ib_qp *qp,
|
|
@@ -1022,7 +1048,7 @@ int ib_modify_qp(struct ib_qp *qp,
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- ret = ib_resolve_eth_l2_attrs(qp, qp_attr, &qp_attr_mask);
|
|
|
|
|
|
+ ret = ib_resolve_eth_dmac(qp, qp_attr, &qp_attr_mask);
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|