diff options
| author | Or Gerlitz <ogerlitz@mellanox.com> | 2013-12-12 11:03:17 -0500 |
|---|---|---|
| committer | Roland Dreier <roland@purestorage.com> | 2014-01-19 18:14:04 -0500 |
| commit | ed4c54e5b4baf55a7a67a80fa766334855c94854 (patch) | |
| tree | 24ee1fc584c644b7d74956be0994f0f4abd36df9 | |
| parent | 37721d8501a9a1fbe87527c24d127a914b29fd7f (diff) | |
IB/core: Resolve Ethernet L2 addresses when modifying QP
Existing user space applications provide only IBoE L3 address
attributes to the kernel when they issue a modify QP modify. To work
with them and let such apps (plus kernel consumers which don't use the
RDMA-CM) keep working transparently under the IBoE GID IP addressing
changes, add an Eth L2 address resolution helper.
Signed-off-by: Moni Shoua <monis@mellanox.co.il>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
| -rw-r--r-- | drivers/infiniband/core/core_priv.h | 2 | ||||
| -rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 4 | ||||
| -rw-r--r-- | drivers/infiniband/core/verbs.c | 43 |
3 files changed, 49 insertions, 0 deletions
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h index a565af5c2d2e..87d1936f5c1c 100644 --- a/drivers/infiniband/core/core_priv.h +++ b/drivers/infiniband/core/core_priv.h | |||
| @@ -49,4 +49,6 @@ void ib_sysfs_cleanup(void); | |||
| 49 | int ib_cache_setup(void); | 49 | int ib_cache_setup(void); |
| 50 | void ib_cache_cleanup(void); | 50 | void ib_cache_cleanup(void); |
| 51 | 51 | ||
| 52 | int ib_resolve_eth_l2_attrs(struct ib_qp *qp, | ||
| 53 | struct ib_qp_attr *qp_attr, int *qp_attr_mask); | ||
| 52 | #endif /* _CORE_PRIV_H */ | 54 | #endif /* _CORE_PRIV_H */ |
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index f1cc83855af6..ea6203ee7bcc 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
| 41 | 41 | ||
| 42 | #include "uverbs.h" | 42 | #include "uverbs.h" |
| 43 | #include "core_priv.h" | ||
| 43 | 44 | ||
| 44 | struct uverbs_lock_class { | 45 | struct uverbs_lock_class { |
| 45 | struct lock_class_key key; | 46 | struct lock_class_key key; |
| @@ -1961,6 +1962,9 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, | |||
| 1961 | attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; | 1962 | attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; |
| 1962 | 1963 | ||
| 1963 | if (qp->real_qp == qp) { | 1964 | if (qp->real_qp == qp) { |
| 1965 | ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask); | ||
| 1966 | if (ret) | ||
| 1967 | goto out; | ||
| 1964 | ret = qp->device->modify_qp(qp, attr, | 1968 | ret = qp->device->modify_qp(qp, attr, |
| 1965 | modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata); | 1969 | modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata); |
| 1966 | } else { | 1970 | } else { |
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 7978394738a3..b3acfc03c74d 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c | |||
| @@ -46,6 +46,8 @@ | |||
| 46 | #include <rdma/ib_cache.h> | 46 | #include <rdma/ib_cache.h> |
| 47 | #include <rdma/ib_addr.h> | 47 | #include <rdma/ib_addr.h> |
| 48 | 48 | ||
| 49 | #include "core_priv.h" | ||
| 50 | |||
| 49 | int ib_rate_to_mult(enum ib_rate rate) | 51 | int ib_rate_to_mult(enum ib_rate rate) |
| 50 | { | 52 | { |
| 51 | switch (rate) { | 53 | switch (rate) { |
| @@ -859,10 +861,51 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, | |||
| 859 | } | 861 | } |
| 860 | EXPORT_SYMBOL(ib_modify_qp_is_ok); | 862 | EXPORT_SYMBOL(ib_modify_qp_is_ok); |
| 861 | 863 | ||
| 864 | int ib_resolve_eth_l2_attrs(struct ib_qp *qp, | ||
| 865 | struct ib_qp_attr *qp_attr, int *qp_attr_mask) | ||
| 866 | { | ||
| 867 | int ret = 0; | ||
| 868 | union ib_gid sgid; | ||
| 869 | |||
| 870 | if ((*qp_attr_mask & IB_QP_AV) && | ||
| 871 | (rdma_port_get_link_layer(qp->device, qp_attr->ah_attr.port_num) == IB_LINK_LAYER_ETHERNET)) { | ||
| 872 | ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num, | ||
| 873 | qp_attr->ah_attr.grh.sgid_index, &sgid); | ||
| 874 | if (ret) | ||
| 875 | goto out; | ||
| 876 | if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) { | ||
| 877 | rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw, qp_attr->ah_attr.dmac); | ||
| 878 | rdma_get_ll_mac((struct in6_addr *)sgid.raw, qp_attr->smac); | ||
| 879 | qp_attr->vlan_id = rdma_get_vlan_id(&sgid); | ||
| 880 | } else { | ||
| 881 | ret = rdma_addr_find_dmac_by_grh(&sgid, &qp_attr->ah_attr.grh.dgid, | ||
| 882 | qp_attr->ah_attr.dmac, &qp_attr->vlan_id); | ||
| 883 | if (ret) | ||
| 884 | goto out; | ||
| 885 | ret = rdma_addr_find_smac_by_sgid(&sgid, qp_attr->smac, NULL); | ||
| 886 | if (ret) | ||
| 887 | goto out; | ||
| 888 | } | ||
| 889 | *qp_attr_mask |= IB_QP_SMAC; | ||
| 890 | if (qp_attr->vlan_id < 0xFFFF) | ||
| 891 | *qp_attr_mask |= IB_QP_VID; | ||
| 892 | } | ||
| 893 | out: | ||
| 894 | return ret; | ||
| 895 | } | ||
| 896 | EXPORT_SYMBOL(ib_resolve_eth_l2_attrs); | ||
| 897 | |||
| 898 | |||
| 862 | int ib_modify_qp(struct ib_qp *qp, | 899 | int ib_modify_qp(struct ib_qp *qp, |
| 863 | struct ib_qp_attr *qp_attr, | 900 | struct ib_qp_attr *qp_attr, |
| 864 | int qp_attr_mask) | 901 | int qp_attr_mask) |
| 865 | { | 902 | { |
| 903 | int ret; | ||
| 904 | |||
| 905 | ret = ib_resolve_eth_l2_attrs(qp, qp_attr, &qp_attr_mask); | ||
| 906 | if (ret) | ||
| 907 | return ret; | ||
| 908 | |||
| 866 | return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL); | 909 | return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL); |
| 867 | } | 910 | } |
| 868 | EXPORT_SYMBOL(ib_modify_qp); | 911 | EXPORT_SYMBOL(ib_modify_qp); |
