diff options
| -rw-r--r-- | drivers/infiniband/core/cma.c | 170 | 
1 files changed, 105 insertions, 65 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 9664131c4eeb..249944c2c537 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c  | |||
| @@ -870,107 +870,138 @@ static inline int cma_any_port(struct sockaddr *addr) | |||
| 870 | return !cma_port(addr); | 870 | return !cma_port(addr); | 
| 871 | } | 871 | } | 
| 872 | 872 | ||
| 873 | static void cma_save_ib_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id, | 873 | static void cma_save_ib_info(struct sockaddr *src_addr, | 
| 874 | struct sockaddr *dst_addr, | ||
| 875 | struct rdma_cm_id *listen_id, | ||
| 874 | struct ib_sa_path_rec *path) | 876 | struct ib_sa_path_rec *path) | 
| 875 | { | 877 | { | 
| 876 | struct sockaddr_ib *listen_ib, *ib; | 878 | struct sockaddr_ib *listen_ib, *ib; | 
| 877 | 879 | ||
| 878 | listen_ib = (struct sockaddr_ib *) &listen_id->route.addr.src_addr; | 880 | listen_ib = (struct sockaddr_ib *) &listen_id->route.addr.src_addr; | 
| 879 | ib = (struct sockaddr_ib *) &id->route.addr.src_addr; | 881 | if (src_addr) { | 
| 880 | ib->sib_family = listen_ib->sib_family; | 882 | ib = (struct sockaddr_ib *)src_addr; | 
| 881 | if (path) { | 883 | ib->sib_family = AF_IB; | 
| 882 | ib->sib_pkey = path->pkey; | 884 | if (path) { | 
| 883 | ib->sib_flowinfo = path->flow_label; | 885 | ib->sib_pkey = path->pkey; | 
| 884 | memcpy(&ib->sib_addr, &path->sgid, 16); | 886 | ib->sib_flowinfo = path->flow_label; | 
| 885 | } else { | 887 | memcpy(&ib->sib_addr, &path->sgid, 16); | 
| 886 | ib->sib_pkey = listen_ib->sib_pkey; | 888 | ib->sib_sid = path->service_id; | 
| 887 | ib->sib_flowinfo = listen_ib->sib_flowinfo; | 889 | ib->sib_scope_id = 0; | 
| 888 | ib->sib_addr = listen_ib->sib_addr; | 890 | } else { | 
| 889 | } | 891 | ib->sib_pkey = listen_ib->sib_pkey; | 
| 890 | ib->sib_sid = listen_ib->sib_sid; | 892 | ib->sib_flowinfo = listen_ib->sib_flowinfo; | 
| 891 | ib->sib_sid_mask = cpu_to_be64(0xffffffffffffffffULL); | 893 | ib->sib_addr = listen_ib->sib_addr; | 
| 892 | ib->sib_scope_id = listen_ib->sib_scope_id; | 894 | ib->sib_sid = listen_ib->sib_sid; | 
| 893 | 895 | ib->sib_scope_id = listen_ib->sib_scope_id; | |
| 894 | if (path) { | 896 | } | 
| 895 | ib = (struct sockaddr_ib *) &id->route.addr.dst_addr; | 897 | ib->sib_sid_mask = cpu_to_be64(0xffffffffffffffffULL); | 
| 896 | ib->sib_family = listen_ib->sib_family; | 898 | } | 
| 897 | ib->sib_pkey = path->pkey; | 899 | if (dst_addr) { | 
| 898 | ib->sib_flowinfo = path->flow_label; | 900 | ib = (struct sockaddr_ib *)dst_addr; | 
| 899 | memcpy(&ib->sib_addr, &path->dgid, 16); | 901 | ib->sib_family = AF_IB; | 
| 902 | if (path) { | ||
| 903 | ib->sib_pkey = path->pkey; | ||
| 904 | ib->sib_flowinfo = path->flow_label; | ||
| 905 | memcpy(&ib->sib_addr, &path->dgid, 16); | ||
| 906 | } | ||
| 900 | } | 907 | } | 
| 901 | } | 908 | } | 
| 902 | 909 | ||
| 903 | static __be16 ss_get_port(const struct sockaddr_storage *ss) | 910 | static void cma_save_ip4_info(struct sockaddr *src_addr, | 
| 904 | { | 911 | struct sockaddr *dst_addr, | 
| 905 | if (ss->ss_family == AF_INET) | 912 | struct cma_hdr *hdr, | 
| 906 | return ((struct sockaddr_in *)ss)->sin_port; | 913 | __be16 local_port) | 
| 907 | else if (ss->ss_family == AF_INET6) | ||
| 908 | return ((struct sockaddr_in6 *)ss)->sin6_port; | ||
| 909 | BUG(); | ||
| 910 | } | ||
| 911 | |||
| 912 | static void cma_save_ip4_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id, | ||
| 913 | struct cma_hdr *hdr) | ||
| 914 | { | 914 | { | 
| 915 | struct sockaddr_in *ip4; | 915 | struct sockaddr_in *ip4; | 
| 916 | 916 | ||
| 917 | ip4 = (struct sockaddr_in *) &id->route.addr.src_addr; | 917 | if (src_addr) { | 
| 918 | ip4->sin_family = AF_INET; | 918 | ip4 = (struct sockaddr_in *)src_addr; | 
| 919 | ip4->sin_addr.s_addr = hdr->dst_addr.ip4.addr; | 919 | ip4->sin_family = AF_INET; | 
| 920 | ip4->sin_port = ss_get_port(&listen_id->route.addr.src_addr); | 920 | ip4->sin_addr.s_addr = hdr->dst_addr.ip4.addr; | 
| 921 | ip4->sin_port = local_port; | ||
| 922 | } | ||
| 921 | 923 | ||
| 922 | ip4 = (struct sockaddr_in *) &id->route.addr.dst_addr; | 924 | if (dst_addr) { | 
| 923 | ip4->sin_family = AF_INET; | 925 | ip4 = (struct sockaddr_in *)dst_addr; | 
| 924 | ip4->sin_addr.s_addr = hdr->src_addr.ip4.addr; | 926 | ip4->sin_family = AF_INET; | 
| 925 | ip4->sin_port = hdr->port; | 927 | ip4->sin_addr.s_addr = hdr->src_addr.ip4.addr; | 
| 928 | ip4->sin_port = hdr->port; | ||
| 929 | } | ||
| 926 | } | 930 | } | 
| 927 | 931 | ||
| 928 | static void cma_save_ip6_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id, | 932 | static void cma_save_ip6_info(struct sockaddr *src_addr, | 
| 929 | struct cma_hdr *hdr) | 933 | struct sockaddr *dst_addr, | 
| 934 | struct cma_hdr *hdr, | ||
| 935 | __be16 local_port) | ||
| 930 | { | 936 | { | 
| 931 | struct sockaddr_in6 *ip6; | 937 | struct sockaddr_in6 *ip6; | 
| 932 | 938 | ||
| 933 | ip6 = (struct sockaddr_in6 *) &id->route.addr.src_addr; | 939 | if (src_addr) { | 
| 934 | ip6->sin6_family = AF_INET6; | 940 | ip6 = (struct sockaddr_in6 *)src_addr; | 
| 935 | ip6->sin6_addr = hdr->dst_addr.ip6; | 941 | ip6->sin6_family = AF_INET6; | 
| 936 | ip6->sin6_port = ss_get_port(&listen_id->route.addr.src_addr); | 942 | ip6->sin6_addr = hdr->dst_addr.ip6; | 
| 943 | ip6->sin6_port = local_port; | ||
| 944 | } | ||
| 937 | 945 | ||
| 938 | ip6 = (struct sockaddr_in6 *) &id->route.addr.dst_addr; | 946 | if (dst_addr) { | 
| 939 | ip6->sin6_family = AF_INET6; | 947 | ip6 = (struct sockaddr_in6 *)dst_addr; | 
| 940 | ip6->sin6_addr = hdr->src_addr.ip6; | 948 | ip6->sin6_family = AF_INET6; | 
| 941 | ip6->sin6_port = hdr->port; | 949 | ip6->sin6_addr = hdr->src_addr.ip6; | 
| 950 | ip6->sin6_port = hdr->port; | ||
| 951 | } | ||
| 942 | } | 952 | } | 
| 943 | 953 | ||
| 944 | static int cma_save_net_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id, | 954 | static u16 cma_port_from_service_id(__be64 service_id) | 
| 945 | struct ib_cm_event *ib_event) | ||
| 946 | { | 955 | { | 
| 947 | struct cma_hdr *hdr; | 956 | return (u16)be64_to_cpu(service_id); | 
| 957 | } | ||
| 948 | 958 | ||
| 949 | if (listen_id->route.addr.src_addr.ss_family == AF_IB) { | 959 | static int cma_save_ip_info(struct sockaddr *src_addr, | 
| 950 | if (ib_event->event == IB_CM_REQ_RECEIVED) | 960 | struct sockaddr *dst_addr, | 
| 951 | cma_save_ib_info(id, listen_id, ib_event->param.req_rcvd.primary_path); | 961 | struct ib_cm_event *ib_event, | 
| 952 | else if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) | 962 | __be64 service_id) | 
| 953 | cma_save_ib_info(id, listen_id, NULL); | 963 | { | 
| 954 | return 0; | 964 | struct cma_hdr *hdr; | 
| 955 | } | 965 | __be16 port; | 
| 956 | 966 | ||
| 957 | hdr = ib_event->private_data; | 967 | hdr = ib_event->private_data; | 
| 958 | if (hdr->cma_version != CMA_VERSION) | 968 | if (hdr->cma_version != CMA_VERSION) | 
| 959 | return -EINVAL; | 969 | return -EINVAL; | 
| 960 | 970 | ||
| 971 | port = htons(cma_port_from_service_id(service_id)); | ||
| 972 | |||
| 961 | switch (cma_get_ip_ver(hdr)) { | 973 | switch (cma_get_ip_ver(hdr)) { | 
| 962 | case 4: | 974 | case 4: | 
| 963 | cma_save_ip4_info(id, listen_id, hdr); | 975 | cma_save_ip4_info(src_addr, dst_addr, hdr, port); | 
| 964 | break; | 976 | break; | 
| 965 | case 6: | 977 | case 6: | 
| 966 | cma_save_ip6_info(id, listen_id, hdr); | 978 | cma_save_ip6_info(src_addr, dst_addr, hdr, port); | 
| 967 | break; | 979 | break; | 
| 968 | default: | 980 | default: | 
| 969 | return -EINVAL; | 981 | return -EINVAL; | 
| 970 | } | 982 | } | 
| 983 | |||
| 971 | return 0; | 984 | return 0; | 
| 972 | } | 985 | } | 
| 973 | 986 | ||
| 987 | static int cma_save_net_info(struct sockaddr *src_addr, | ||
| 988 | struct sockaddr *dst_addr, | ||
| 989 | struct rdma_cm_id *listen_id, | ||
| 990 | struct ib_cm_event *ib_event, | ||
| 991 | sa_family_t sa_family, __be64 service_id) | ||
| 992 | { | ||
| 993 | if (sa_family == AF_IB) { | ||
| 994 | if (ib_event->event == IB_CM_REQ_RECEIVED) | ||
| 995 | cma_save_ib_info(src_addr, dst_addr, listen_id, | ||
| 996 | ib_event->param.req_rcvd.primary_path); | ||
| 997 | else if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED) | ||
| 998 | cma_save_ib_info(src_addr, dst_addr, listen_id, NULL); | ||
| 999 | return 0; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | return cma_save_ip_info(src_addr, dst_addr, ib_event, service_id); | ||
| 1003 | } | ||
| 1004 | |||
| 974 | static inline int cma_user_data_offset(struct rdma_id_private *id_priv) | 1005 | static inline int cma_user_data_offset(struct rdma_id_private *id_priv) | 
| 975 | { | 1006 | { | 
| 976 | return cma_family(id_priv) == AF_IB ? 0 : sizeof(struct cma_hdr); | 1007 | return cma_family(id_priv) == AF_IB ? 0 : sizeof(struct cma_hdr); | 
| @@ -1221,6 +1252,9 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, | |||
| 1221 | struct rdma_id_private *id_priv; | 1252 | struct rdma_id_private *id_priv; | 
| 1222 | struct rdma_cm_id *id; | 1253 | struct rdma_cm_id *id; | 
| 1223 | struct rdma_route *rt; | 1254 | struct rdma_route *rt; | 
| 1255 | const sa_family_t ss_family = listen_id->route.addr.src_addr.ss_family; | ||
| 1256 | const __be64 service_id = | ||
| 1257 | ib_event->param.req_rcvd.primary_path->service_id; | ||
| 1224 | int ret; | 1258 | int ret; | 
| 1225 | 1259 | ||
| 1226 | id = rdma_create_id(listen_id->event_handler, listen_id->context, | 1260 | id = rdma_create_id(listen_id->event_handler, listen_id->context, | 
| @@ -1229,7 +1263,9 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, | |||
| 1229 | return NULL; | 1263 | return NULL; | 
| 1230 | 1264 | ||
| 1231 | id_priv = container_of(id, struct rdma_id_private, id); | 1265 | id_priv = container_of(id, struct rdma_id_private, id); | 
| 1232 | if (cma_save_net_info(id, listen_id, ib_event)) | 1266 | if (cma_save_net_info((struct sockaddr *)&id->route.addr.src_addr, | 
| 1267 | (struct sockaddr *)&id->route.addr.dst_addr, | ||
| 1268 | listen_id, ib_event, ss_family, service_id)) | ||
| 1233 | goto err; | 1269 | goto err; | 
| 1234 | 1270 | ||
| 1235 | rt = &id->route; | 1271 | rt = &id->route; | 
| @@ -1267,6 +1303,7 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, | |||
| 1267 | { | 1303 | { | 
| 1268 | struct rdma_id_private *id_priv; | 1304 | struct rdma_id_private *id_priv; | 
| 1269 | struct rdma_cm_id *id; | 1305 | struct rdma_cm_id *id; | 
| 1306 | const sa_family_t ss_family = listen_id->route.addr.src_addr.ss_family; | ||
| 1270 | int ret; | 1307 | int ret; | 
| 1271 | 1308 | ||
| 1272 | id = rdma_create_id(listen_id->event_handler, listen_id->context, | 1309 | id = rdma_create_id(listen_id->event_handler, listen_id->context, | 
| @@ -1275,7 +1312,10 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id, | |||
| 1275 | return NULL; | 1312 | return NULL; | 
| 1276 | 1313 | ||
| 1277 | id_priv = container_of(id, struct rdma_id_private, id); | 1314 | id_priv = container_of(id, struct rdma_id_private, id); | 
| 1278 | if (cma_save_net_info(id, listen_id, ib_event)) | 1315 | if (cma_save_net_info((struct sockaddr *)&id->route.addr.src_addr, | 
| 1316 | (struct sockaddr *)&id->route.addr.dst_addr, | ||
| 1317 | listen_id, ib_event, ss_family, | ||
| 1318 | ib_event->param.sidr_req_rcvd.service_id)) | ||
| 1279 | goto err; | 1319 | goto err; | 
| 1280 | 1320 | ||
| 1281 | if (!cma_any_addr((struct sockaddr *) &id->route.addr.src_addr)) { | 1321 | if (!cma_any_addr((struct sockaddr *) &id->route.addr.src_addr)) { | 
