diff options
-rw-r--r-- | drivers/infiniband/core/ucma.c | 35 | ||||
-rw-r--r-- | include/uapi/rdma/rdma_user_cm.h | 9 |
2 files changed, 43 insertions, 1 deletions
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 18bdccc0c2ec..722f2ff0400f 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c | |||
@@ -750,6 +750,38 @@ static ssize_t ucma_query_addr(struct ucma_context *ctx, | |||
750 | return ret; | 750 | return ret; |
751 | } | 751 | } |
752 | 752 | ||
753 | static ssize_t ucma_query_path(struct ucma_context *ctx, | ||
754 | void __user *response, int out_len) | ||
755 | { | ||
756 | struct rdma_ucm_query_path_resp *resp; | ||
757 | int i, ret = 0; | ||
758 | |||
759 | if (out_len < sizeof(*resp)) | ||
760 | return -ENOSPC; | ||
761 | |||
762 | resp = kzalloc(out_len, GFP_KERNEL); | ||
763 | if (!resp) | ||
764 | return -ENOMEM; | ||
765 | |||
766 | resp->num_paths = ctx->cm_id->route.num_paths; | ||
767 | for (i = 0, out_len -= sizeof(*resp); | ||
768 | i < resp->num_paths && out_len > sizeof(struct ib_path_rec_data); | ||
769 | i++, out_len -= sizeof(struct ib_path_rec_data)) { | ||
770 | |||
771 | resp->path_data[i].flags = IB_PATH_GMP | IB_PATH_PRIMARY | | ||
772 | IB_PATH_BIDIRECTIONAL; | ||
773 | ib_sa_pack_path(&ctx->cm_id->route.path_rec[i], | ||
774 | &resp->path_data[i].path_rec); | ||
775 | } | ||
776 | |||
777 | if (copy_to_user(response, resp, | ||
778 | sizeof(*resp) + (i * sizeof(struct ib_path_rec_data)))) | ||
779 | ret = -EFAULT; | ||
780 | |||
781 | kfree(resp); | ||
782 | return ret; | ||
783 | } | ||
784 | |||
753 | static ssize_t ucma_query(struct ucma_file *file, | 785 | static ssize_t ucma_query(struct ucma_file *file, |
754 | const char __user *inbuf, | 786 | const char __user *inbuf, |
755 | int in_len, int out_len) | 787 | int in_len, int out_len) |
@@ -771,6 +803,9 @@ static ssize_t ucma_query(struct ucma_file *file, | |||
771 | case RDMA_USER_CM_QUERY_ADDR: | 803 | case RDMA_USER_CM_QUERY_ADDR: |
772 | ret = ucma_query_addr(ctx, response, out_len); | 804 | ret = ucma_query_addr(ctx, response, out_len); |
773 | break; | 805 | break; |
806 | case RDMA_USER_CM_QUERY_PATH: | ||
807 | ret = ucma_query_path(ctx, response, out_len); | ||
808 | break; | ||
774 | default: | 809 | default: |
775 | ret = -ENOSYS; | 810 | ret = -ENOSYS; |
776 | break; | 811 | break; |
diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h index 3ea7e7a4d54b..07eb6cfa926c 100644 --- a/include/uapi/rdma/rdma_user_cm.h +++ b/include/uapi/rdma/rdma_user_cm.h | |||
@@ -115,7 +115,8 @@ struct rdma_ucm_resolve_route { | |||
115 | }; | 115 | }; |
116 | 116 | ||
117 | enum { | 117 | enum { |
118 | RDMA_USER_CM_QUERY_ADDR | 118 | RDMA_USER_CM_QUERY_ADDR, |
119 | RDMA_USER_CM_QUERY_PATH | ||
119 | }; | 120 | }; |
120 | 121 | ||
121 | struct rdma_ucm_query { | 122 | struct rdma_ucm_query { |
@@ -145,6 +146,12 @@ struct rdma_ucm_query_addr_resp { | |||
145 | struct sockaddr_storage dst_addr; | 146 | struct sockaddr_storage dst_addr; |
146 | }; | 147 | }; |
147 | 148 | ||
149 | struct rdma_ucm_query_path_resp { | ||
150 | __u32 num_paths; | ||
151 | __u32 reserved; | ||
152 | struct ib_path_rec_data path_data[0]; | ||
153 | }; | ||
154 | |||
148 | struct rdma_ucm_conn_param { | 155 | struct rdma_ucm_conn_param { |
149 | __u32 qp_num; | 156 | __u32 qp_num; |
150 | __u32 qkey; | 157 | __u32 qkey; |