param->retry_count = cm_req_get_retry_count(req_msg);
        param->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg);
        param->srq = cm_req_get_srq(req_msg);
+       param->ppath_sgid_attr = cm_id_priv->av.ah_attr.grh.sgid_attr;
        work->cm_event.private_data = &req_msg->private_data;
 }
 
 EXPORT_SYMBOL(ib_send_cm_sidr_req);
 
 static void cm_format_sidr_req_event(struct cm_work *work,
+                                    const struct cm_id_private *rx_cm_id,
                                     struct ib_cm_id *listen_id)
 {
        struct cm_sidr_req_msg *sidr_req_msg;
        param->service_id = sidr_req_msg->service_id;
        param->bth_pkey = cm_get_bth_pkey(work);
        param->port = work->port->port_num;
+       param->sgid_attr = rx_cm_id->av.ah_attr.grh.sgid_attr;
        work->cm_event.private_data = &sidr_req_msg->private_data;
 }
 
        cm_id_priv->id.service_id = sidr_req_msg->service_id;
        cm_id_priv->id.service_mask = ~cpu_to_be64(0);
 
-       cm_format_sidr_req_event(work, &cur_cm_id_priv->id);
+       cm_format_sidr_req_event(work, cm_id_priv, &cur_cm_id_priv->id);
        cm_process_work(cm_id_priv, work);
        cm_deref_id(cur_cm_id_priv);
        return 0;
 
        }
 }
 
+static struct net_device *
+roce_get_net_dev_by_cm_event(const struct ib_cm_event *ib_event)
+{
+       const struct ib_gid_attr *sgid_attr = NULL;
+
+       if (ib_event->event == IB_CM_REQ_RECEIVED)
+               sgid_attr = ib_event->param.req_rcvd.ppath_sgid_attr;
+       else if (ib_event->event == IB_CM_SIDR_REQ_RECEIVED)
+               sgid_attr = ib_event->param.sidr_req_rcvd.sgid_attr;
+
+       if (!sgid_attr)
+               return NULL;
+       dev_hold(sgid_attr->ndev);
+       return sgid_attr->ndev;
+}
+
 static struct net_device *cma_get_net_dev(struct ib_cm_event *ib_event,
                                          struct cma_req_info *req)
 {
        if (err)
                return ERR_PTR(err);
 
-       net_dev = ib_get_net_dev_by_params(req->device, req->port, req->pkey,
-                                          gid, listen_addr);
+       if (rdma_protocol_roce(req->device, req->port))
+               net_dev = roce_get_net_dev_by_cm_event(ib_event);
+       else
+               net_dev = ib_get_net_dev_by_params(req->device, req->port,
+                                                  req->pkey,
+                                                  gid, listen_addr);
        if (!net_dev)
                return ERR_PTR(-ENODEV);
 
                if (PTR_ERR(*net_dev) == -EAFNOSUPPORT) {
                        /* Assuming the protocol is AF_IB */
                        *net_dev = NULL;
-               } else if (rdma_protocol_roce(req.device, req.port)) {
-                       /* TODO find the net dev matching the request parameters
-                        * through the RoCE GID table */
-                       *net_dev = NULL;
                } else {
                        return ERR_CAST(*net_dev);
                }
 
        struct sa_path_rec      *primary_path;
        struct sa_path_rec      *alternate_path;
 
+       /*
+        * SGID attribute of the primary path. Currently only
+        * useful for RoCE. Alternate path GID attributes
+        * are not yet supported.
+        */
+       const struct ib_gid_attr *ppath_sgid_attr;
+
        __be64                  remote_ca_guid;
        u32                     remote_qkey;
        u32                     remote_qpn;
 struct ib_cm_sidr_req_event_param {
        struct ib_cm_id         *listen_id;
        __be64                  service_id;
+
+       /*
+        * SGID attribute of the request. Currently only
+        * useful for RoCE.
+        */
+       const struct ib_gid_attr *sgid_attr;
        /* P_Key that was used by the GMP's BTH header */
        u16                     bth_pkey;
        u8                      port;