IB/core: Convert ah_attr from OPA to IB when copying to user
authorDasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com>
Thu, 8 Jun 2017 17:37:43 +0000 (13:37 -0400)
committerDoug Ledford <dledford@redhat.com>
Tue, 8 Aug 2017 18:47:18 +0000 (14:47 -0400)
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>
drivers/infiniband/core/ucm.c
drivers/infiniband/core/ucma.c
drivers/infiniband/core/uverbs_marshall.c
include/rdma/ib_marshall.h

index 112099c86a19a225e3a815bd599a15f10262d083..f2a7f62c2834fac07b9712db723c144c8986b9dd 100644 (file)
@@ -618,7 +618,7 @@ static ssize_t ib_ucm_init_qp_attr(struct ib_ucm_file *file,
        if (result)
                goto out;
 
-       ib_copy_qp_attr_to_user(&resp, &qp_attr);
+       ib_copy_qp_attr_to_user(ctx->cm_id->device, &resp, &qp_attr);
 
        if (copy_to_user((void __user *)(unsigned long)cmd.response,
                         &resp, sizeof(resp)))
index 276f0ef835bdd9d1af9137e12da5ca2452bff87f..eb85b546e223c7fe30a52198d34a8601bfd49629 100644 (file)
@@ -248,14 +248,15 @@ static void ucma_copy_conn_event(struct rdma_ucm_conn_param *dst,
        dst->qp_num = src->qp_num;
 }
 
-static void ucma_copy_ud_event(struct rdma_ucm_ud_param *dst,
+static void ucma_copy_ud_event(struct ib_device *device,
+                              struct rdma_ucm_ud_param *dst,
                               struct rdma_ud_param *src)
 {
        if (src->private_data_len)
                memcpy(dst->private_data, src->private_data,
                       src->private_data_len);
        dst->private_data_len = src->private_data_len;
-       ib_copy_ah_attr_to_user(&dst->ah_attr, &src->ah_attr);
+       ib_copy_ah_attr_to_user(device, &dst->ah_attr, &src->ah_attr);
        dst->qp_num = src->qp_num;
        dst->qkey = src->qkey;
 }
@@ -335,7 +336,8 @@ static int ucma_event_handler(struct rdma_cm_id *cm_id,
        uevent->resp.event = event->event;
        uevent->resp.status = event->status;
        if (cm_id->qp_type == IB_QPT_UD)
-               ucma_copy_ud_event(&uevent->resp.param.ud, &event->param.ud);
+               ucma_copy_ud_event(cm_id->device, &uevent->resp.param.ud,
+                                  &event->param.ud);
        else
                ucma_copy_conn_event(&uevent->resp.param.conn,
                                     &event->param.conn);
@@ -1157,7 +1159,7 @@ static ssize_t ucma_init_qp_attr(struct ucma_file *file,
        if (ret)
                goto out;
 
-       ib_copy_qp_attr_to_user(&resp, &qp_attr);
+       ib_copy_qp_attr_to_user(ctx->cm_id->device, &resp, &qp_attr);
        if (copy_to_user((void __user *)(unsigned long)cmd.response,
                         &resp, sizeof(resp)))
                ret = -EFAULT;
index 94fd989c90600b2640d2fb36f2397c9814160583..bd0acf376af0f011413a19bcc609d6844e0cc21a 100644 (file)
 #include <linux/export.h>
 #include <rdma/ib_marshall.h>
 
-void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
-                            struct rdma_ah_attr *src)
+#define OPA_DEFAULT_GID_PREFIX cpu_to_be64(0xfe80000000000000ULL)
+static int rdma_ah_conv_opa_to_ib(struct ib_device *dev,
+                                 struct rdma_ah_attr *ib,
+                                 struct rdma_ah_attr *opa)
 {
+       struct ib_port_attr port_attr;
+       int ret = 0;
+
+       /* Do structure copy and the over-write fields */
+       *ib = *opa;
+
+       ib->type = RDMA_AH_ATTR_TYPE_IB;
+       rdma_ah_set_grh(ib, NULL, 0, 0, 1, 0);
+
+       if (ib_query_port(dev, opa->port_num, &port_attr)) {
+               /* Set to default subnet to indicate error */
+               rdma_ah_set_subnet_prefix(ib, OPA_DEFAULT_GID_PREFIX);
+               ret = -EINVAL;
+       } else {
+               rdma_ah_set_subnet_prefix(ib,
+                                         cpu_to_be64(port_attr.subnet_prefix));
+       }
+       rdma_ah_set_interface_id(ib, OPA_MAKE_ID(rdma_ah_get_dlid(opa)));
+       return ret;
+}
+
+void ib_copy_ah_attr_to_user(struct ib_device *device,
+                            struct ib_uverbs_ah_attr *dst,
+                            struct rdma_ah_attr *ah_attr)
+{
+       struct rdma_ah_attr *src = ah_attr;
+       struct rdma_ah_attr conv_ah;
+
        memset(&dst->grh.reserved, 0, sizeof(dst->grh.reserved));
+
+       if ((ah_attr->type == RDMA_AH_ATTR_TYPE_OPA) &&
+           (rdma_ah_get_dlid(ah_attr) >=
+            be16_to_cpu(IB_MULTICAST_LID_BASE)) &&
+           (!rdma_ah_conv_opa_to_ib(device, &conv_ah, ah_attr)))
+               src = &conv_ah;
+
        dst->dlid                  = rdma_ah_get_dlid(src);
        dst->sl                    = rdma_ah_get_sl(src);
        dst->src_path_bits         = rdma_ah_get_path_bits(src);
@@ -57,7 +94,8 @@ void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
 }
 EXPORT_SYMBOL(ib_copy_ah_attr_to_user);
 
-void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
+void ib_copy_qp_attr_to_user(struct ib_device *device,
+                            struct ib_uverbs_qp_attr *dst,
                             struct ib_qp_attr *src)
 {
        dst->qp_state           = src->qp_state;
@@ -76,8 +114,8 @@ void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
        dst->max_recv_sge       = src->cap.max_recv_sge;
        dst->max_inline_data    = src->cap.max_inline_data;
 
-       ib_copy_ah_attr_to_user(&dst->ah_attr, &src->ah_attr);
-       ib_copy_ah_attr_to_user(&dst->alt_ah_attr, &src->alt_ah_attr);
+       ib_copy_ah_attr_to_user(device, &dst->ah_attr, &src->ah_attr);
+       ib_copy_ah_attr_to_user(device, &dst->alt_ah_attr, &src->alt_ah_attr);
 
        dst->pkey_index         = src->pkey_index;
        dst->alt_pkey_index     = src->alt_pkey_index;
index 68cef3bd50fb97730df5112d4dc88a8c9923f46d..8ebf84ae9ed161a73d061515a80b1f7d198ba48a 100644 (file)
 #include <rdma/ib_user_verbs.h>
 #include <rdma/ib_user_sa.h>
 
-void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
+void ib_copy_qp_attr_to_user(struct ib_device *device,
+                            struct ib_uverbs_qp_attr *dst,
                             struct ib_qp_attr *src);
 
-void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
+void ib_copy_ah_attr_to_user(struct ib_device *device,
+                            struct ib_uverbs_ah_attr *dst,
                             struct rdma_ah_attr *src);
 
 void ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,