Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/core: Convert ah_attr from OPA to IB when copying to user

OPA address handle atttibutes that have 32 bit LIDs would have to
be converted to IB address handle attribute with the LID field
programmed in the GID before copying to user space.

Signed-off-by: Dasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com>
Reviewed-by: Don Hiatt <don.hiatt@intel.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>

authored by

Dasaratharaman Chandramouli and committed by
Doug Ledford
d541e455 520eccdf

+54 -12
+1 -1
drivers/infiniband/core/ucm.c
··· 618 618 if (result) 619 619 goto out; 620 620 621 - ib_copy_qp_attr_to_user(&resp, &qp_attr); 621 + ib_copy_qp_attr_to_user(ctx->cm_id->device, &resp, &qp_attr); 622 622 623 623 if (copy_to_user((void __user *)(unsigned long)cmd.response, 624 624 &resp, sizeof(resp)))
+6 -4
drivers/infiniband/core/ucma.c
··· 248 248 dst->qp_num = src->qp_num; 249 249 } 250 250 251 - static void ucma_copy_ud_event(struct rdma_ucm_ud_param *dst, 251 + static void ucma_copy_ud_event(struct ib_device *device, 252 + struct rdma_ucm_ud_param *dst, 252 253 struct rdma_ud_param *src) 253 254 { 254 255 if (src->private_data_len) 255 256 memcpy(dst->private_data, src->private_data, 256 257 src->private_data_len); 257 258 dst->private_data_len = src->private_data_len; 258 - ib_copy_ah_attr_to_user(&dst->ah_attr, &src->ah_attr); 259 + ib_copy_ah_attr_to_user(device, &dst->ah_attr, &src->ah_attr); 259 260 dst->qp_num = src->qp_num; 260 261 dst->qkey = src->qkey; 261 262 } ··· 336 335 uevent->resp.event = event->event; 337 336 uevent->resp.status = event->status; 338 337 if (cm_id->qp_type == IB_QPT_UD) 339 - ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud); 338 + ucma_copy_ud_event(cm_id->device, &uevent->resp.param.ud, 339 + &event->param.ud); 340 340 else 341 341 ucma_copy_conn_event(&uevent->resp.param.conn, 342 342 &event->param.conn); ··· 1159 1157 if (ret) 1160 1158 goto out; 1161 1159 1162 - ib_copy_qp_attr_to_user(&resp, &qp_attr); 1160 + ib_copy_qp_attr_to_user(ctx->cm_id->device, &resp, &qp_attr); 1163 1161 if (copy_to_user((void __user *)(unsigned long)cmd.response, 1164 1162 &resp, sizeof(resp))) 1165 1163 ret = -EFAULT;
+43 -5
drivers/infiniband/core/uverbs_marshall.c
··· 33 33 #include <linux/export.h> 34 34 #include <rdma/ib_marshall.h> 35 35 36 - void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst, 37 - struct rdma_ah_attr *src) 36 + #define OPA_DEFAULT_GID_PREFIX cpu_to_be64(0xfe80000000000000ULL) 37 + static int rdma_ah_conv_opa_to_ib(struct ib_device *dev, 38 + struct rdma_ah_attr *ib, 39 + struct rdma_ah_attr *opa) 38 40 { 41 + struct ib_port_attr port_attr; 42 + int ret = 0; 43 + 44 + /* Do structure copy and the over-write fields */ 45 + *ib = *opa; 46 + 47 + ib->type = RDMA_AH_ATTR_TYPE_IB; 48 + rdma_ah_set_grh(ib, NULL, 0, 0, 1, 0); 49 + 50 + if (ib_query_port(dev, opa->port_num, &port_attr)) { 51 + /* Set to default subnet to indicate error */ 52 + rdma_ah_set_subnet_prefix(ib, OPA_DEFAULT_GID_PREFIX); 53 + ret = -EINVAL; 54 + } else { 55 + rdma_ah_set_subnet_prefix(ib, 56 + cpu_to_be64(port_attr.subnet_prefix)); 57 + } 58 + rdma_ah_set_interface_id(ib, OPA_MAKE_ID(rdma_ah_get_dlid(opa))); 59 + return ret; 60 + } 61 + 62 + void ib_copy_ah_attr_to_user(struct ib_device *device, 63 + struct ib_uverbs_ah_attr *dst, 64 + struct rdma_ah_attr *ah_attr) 65 + { 66 + struct rdma_ah_attr *src = ah_attr; 67 + struct rdma_ah_attr conv_ah; 68 + 39 69 memset(&dst->grh.reserved, 0, sizeof(dst->grh.reserved)); 70 + 71 + if ((ah_attr->type == RDMA_AH_ATTR_TYPE_OPA) && 72 + (rdma_ah_get_dlid(ah_attr) >= 73 + be16_to_cpu(IB_MULTICAST_LID_BASE)) && 74 + (!rdma_ah_conv_opa_to_ib(device, &conv_ah, ah_attr))) 75 + src = &conv_ah; 76 + 40 77 dst->dlid = rdma_ah_get_dlid(src); 41 78 dst->sl = rdma_ah_get_sl(src); 42 79 dst->src_path_bits = rdma_ah_get_path_bits(src); ··· 94 57 } 95 58 EXPORT_SYMBOL(ib_copy_ah_attr_to_user); 96 59 97 - void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst, 60 + void ib_copy_qp_attr_to_user(struct ib_device *device, 61 + struct ib_uverbs_qp_attr *dst, 98 62 struct ib_qp_attr *src) 99 63 { 100 64 dst->qp_state = src->qp_state; ··· 114 76 dst->max_recv_sge = src->cap.max_recv_sge; 115 77 dst->max_inline_data = src->cap.max_inline_data; 116 78 117 - ib_copy_ah_attr_to_user(&dst->ah_attr, &src->ah_attr); 118 - ib_copy_ah_attr_to_user(&dst->alt_ah_attr, &src->alt_ah_attr); 79 + ib_copy_ah_attr_to_user(device, &dst->ah_attr, &src->ah_attr); 80 + ib_copy_ah_attr_to_user(device, &dst->alt_ah_attr, &src->alt_ah_attr); 119 81 120 82 dst->pkey_index = src->pkey_index; 121 83 dst->alt_pkey_index = src->alt_pkey_index;
+4 -2
include/rdma/ib_marshall.h
··· 38 38 #include <rdma/ib_user_verbs.h> 39 39 #include <rdma/ib_user_sa.h> 40 40 41 - void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst, 41 + void ib_copy_qp_attr_to_user(struct ib_device *device, 42 + struct ib_uverbs_qp_attr *dst, 42 43 struct ib_qp_attr *src); 43 44 44 - void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst, 45 + void ib_copy_ah_attr_to_user(struct ib_device *device, 46 + struct ib_uverbs_ah_attr *dst, 45 47 struct rdma_ah_attr *src); 46 48 47 49 void ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,