]> git.openfabrics.org - ~emulex/for-vlad/old/compat-rdma.git/commitdiff
IB/core: Added fixes from upstream
authorVladimir Sokolovsky <vlad@mellanox.com>
Tue, 12 May 2015 06:37:58 +0000 (09:37 +0300)
committerVladimir Sokolovsky <vlad@mellanox.com>
Tue, 12 May 2015 07:50:55 +0000 (10:50 +0300)
 0fb8bcf022f19a375d7c4bd79ac513da8ae6d78b IB/core: Fix deadlock on uverbs modify_qp error flow
 c1bd6cde8efda081af9d4f1fa4105e114b9b5cf5 IB/core: Do not resolve VLAN if already resolved
 514f3ddffe7c366af7921fdddaae3811e3efce03 IB/core: Fix mgid key handling in SA agent multicast
 346f98b41b76281bd0b748fb86bc1953c9fd9fe2 IB/addr: Improve address resolution callback scheduling
 66578b0b2f69659f00b6169e6fe7377c4b100d18 IB/core: don't disallow registering region starting at 0x0
 a233c4b54c882817ae9dd73384d5dd75d3e57498 ib_uverbs: Fix pages leak when using XRC SRQs
 0d0f738f6a11856a704dcd8fd3a008b200f17625 IB/core: Fix unaligned accesses

Signed-off-by: Vladimir Sokolovsky <vlad@mellanox.com>
linux-next-cherry-picks/0011-IB-core-Fix-deadlock-on-uverbs-modify_qp-error-flow.patch [new file with mode: 0644]
linux-next-cherry-picks/0012-IB-core-Do-not-resolve-VLAN-if-already-resolved.patch [new file with mode: 0644]
linux-next-cherry-picks/0013-IB-core-Fix-mgid-key-handling-in-SA-agent-multicast-.patch [new file with mode: 0644]
linux-next-cherry-picks/0014-IB-addr-Improve-address-resolution-callback-scheduli.patch [new file with mode: 0644]
linux-next-cherry-picks/0015-IB-core-don-t-disallow-registering-region-starting-a.patch [new file with mode: 0644]
linux-next-cherry-picks/0016-ib_uverbs-Fix-pages-leak-when-using-XRC-SRQs.patch [new file with mode: 0644]
linux-next-cherry-picks/0017-IB-core-Fix-unaligned-accesses.patch [new file with mode: 0644]

diff --git a/linux-next-cherry-picks/0011-IB-core-Fix-deadlock-on-uverbs-modify_qp-error-flow.patch b/linux-next-cherry-picks/0011-IB-core-Fix-deadlock-on-uverbs-modify_qp-error-flow.patch
new file mode 100644 (file)
index 0000000..c64640b
--- /dev/null
@@ -0,0 +1,50 @@
+From 0fb8bcf022f19a375d7c4bd79ac513da8ae6d78b Mon Sep 17 00:00:00 2001
+From: Moshe Lazer <moshel@mellanox.com>
+Date: Thu, 5 Feb 2015 13:53:52 +0200
+Subject: [PATCH] IB/core: Fix deadlock on uverbs modify_qp error flow
+
+The deadlock occurs in __uverbs_modify_qp: we take a lock (idr_read_qp)
+and in case of failure in ib_resolve_eth_l2_attrs we don't release
+it (put_qp_read).  Fix that.
+
+Fixes: ed4c54e5b4ba ("IB/core: Resolve Ethernet L2 addresses when modifying QP")
+Signed-off-by: Moshe Lazer <moshel@mellanox.com>
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+---
+ drivers/infiniband/core/uverbs_cmd.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
+index b7943ff..6c52e72 100644
+--- a/drivers/infiniband/core/uverbs_cmd.c
++++ b/drivers/infiniband/core/uverbs_cmd.c
+@@ -2091,20 +2091,21 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
+       if (qp->real_qp == qp) {
+               ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask);
+               if (ret)
+-                      goto out;
++                      goto release_qp;
+               ret = qp->device->modify_qp(qp, attr,
+                       modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
+       } else {
+               ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
+       }
+-      put_qp_read(qp);
+-
+       if (ret)
+-              goto out;
++              goto release_qp;
+       ret = in_len;
++release_qp:
++      put_qp_read(qp);
++
+ out:
+       kfree(attr);
+-- 
+1.8.3.1
+
diff --git a/linux-next-cherry-picks/0012-IB-core-Do-not-resolve-VLAN-if-already-resolved.patch b/linux-next-cherry-picks/0012-IB-core-Do-not-resolve-VLAN-if-already-resolved.patch
new file mode 100644 (file)
index 0000000..1724136
--- /dev/null
@@ -0,0 +1,36 @@
+From c1bd6cde8efda081af9d4f1fa4105e114b9b5cf5 Mon Sep 17 00:00:00 2001
+From: Moni Shoua <monis@mellanox.com>
+Date: Wed, 19 Nov 2014 11:28:18 +0200
+Subject: [PATCH] IB/core: Do not resolve VLAN if already resolved
+
+For RoCE, resolution of layer 2 address attributes forces no VLAN if
+link-local GIDs are used.  This patch allows applications to choose
+the VLAN ID for link-local based RoCE GIDs by setting IB_QP_VID in
+their QP attribute mask, and prevents the core from overriding this
+choice.
+
+Cc: Ursula Braun <ursula.braun@de.ibm.com>
+Signed-off-by: Moni Shoua <monis@mellanox.com>
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+---
+ drivers/infiniband/core/verbs.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
+index c2b89cc..f93eb8d 100644
+--- a/drivers/infiniband/core/verbs.c
++++ b/drivers/infiniband/core/verbs.c
+@@ -879,7 +879,8 @@ int ib_resolve_eth_l2_attrs(struct ib_qp *qp,
+               if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) {
+                       rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw, qp_attr->ah_attr.dmac);
+                       rdma_get_ll_mac((struct in6_addr *)sgid.raw, qp_attr->smac);
+-                      qp_attr->vlan_id = rdma_get_vlan_id(&sgid);
++                      if (!(*qp_attr_mask & IB_QP_VID))
++                              qp_attr->vlan_id = rdma_get_vlan_id(&sgid);
+               } else {
+                       ret = rdma_addr_find_dmac_by_grh(&sgid, &qp_attr->ah_attr.grh.dgid,
+                                       qp_attr->ah_attr.dmac, &qp_attr->vlan_id);
+-- 
+1.8.3.1
+
diff --git a/linux-next-cherry-picks/0013-IB-core-Fix-mgid-key-handling-in-SA-agent-multicast-.patch b/linux-next-cherry-picks/0013-IB-core-Fix-mgid-key-handling-in-SA-agent-multicast-.patch
new file mode 100644 (file)
index 0000000..3366ac1
--- /dev/null
@@ -0,0 +1,67 @@
+From 514f3ddffe7c366af7921fdddaae3811e3efce03 Mon Sep 17 00:00:00 2001
+From: Jack Morgenstein <jackm@dev.mellanox.co.il>
+Date: Wed, 19 Nov 2014 11:08:58 +0200
+Subject: [PATCH] IB/core: Fix mgid key handling in SA agent multicast
+ data-base
+
+Applications can request that the SM assign an MGID by passing a mcast
+member request containing MGID = 0. When the SM responds by sending
+the allocated MGID, this MGID replaces the 0-MGID in the multicast group.
+
+However, the MGID field in the group is also the key field in the IB
+core multicast code rbtree containing the multicast groups for the
+port.
+
+Since this is a key field, correct handling requires that the group
+entry be deleted from the rbtree and then re-inserted with the new
+key, so that the table structure is properly maintained.
+
+The current code does not do this correctly.  Correct operation
+requires that if the key-field gid has changed at all, it should be
+deleted and re-inserted.
+
+Note that when inserting, if the new MGID is zero (not the case here
+but the code should handle this correctly), we allow duplicate entries
+for 0-MGIDs.
+
+Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Acked-by: Sean Hefty <sean.hefty@intel.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+---
+ drivers/infiniband/core/multicast.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
+index d2360a8..fa17b55 100644
+--- a/drivers/infiniband/core/multicast.c
++++ b/drivers/infiniband/core/multicast.c
+@@ -525,17 +525,22 @@ static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
+       if (status)
+               process_join_error(group, status);
+       else {
++              int mgids_changed, is_mgid0;
+               ib_find_pkey(group->port->dev->device, group->port->port_num,
+                            be16_to_cpu(rec->pkey), &pkey_index);
+               spin_lock_irq(&group->port->lock);
+-              group->rec = *rec;
+               if (group->state == MCAST_BUSY &&
+                   group->pkey_index == MCAST_INVALID_PKEY_INDEX)
+                       group->pkey_index = pkey_index;
+-              if (!memcmp(&mgid0, &group->rec.mgid, sizeof mgid0)) {
++              mgids_changed = memcmp(&rec->mgid, &group->rec.mgid,
++                                     sizeof(group->rec.mgid));
++              group->rec = *rec;
++              if (mgids_changed) {
+                       rb_erase(&group->node, &group->port->table);
+-                      mcast_insert(group->port, group, 1);
++                      is_mgid0 = !memcmp(&mgid0, &group->rec.mgid,
++                                         sizeof(mgid0));
++                      mcast_insert(group->port, group, is_mgid0);
+               }
+               spin_unlock_irq(&group->port->lock);
+       }
+-- 
+1.8.3.1
+
diff --git a/linux-next-cherry-picks/0014-IB-addr-Improve-address-resolution-callback-scheduli.patch b/linux-next-cherry-picks/0014-IB-addr-Improve-address-resolution-callback-scheduli.patch
new file mode 100644 (file)
index 0000000..306c104
--- /dev/null
@@ -0,0 +1,76 @@
+From 346f98b41b76281bd0b748fb86bc1953c9fd9fe2 Mon Sep 17 00:00:00 2001
+From: Or Kehati <ork@mellanox.com>
+Date: Wed, 29 Oct 2014 16:32:04 +0200
+Subject: [PATCH] IB/addr: Improve address resolution callback scheduling
+
+Address resolution always does a context switch to a work-queue to
+deliver the address resolution event.  When the IP address is already
+cached in the system ARP table, we're going through the following:
+chain:
+
+    rdma_resolve_ip --> addr_resolve (cache hit) -->
+
+which ends up with:
+
+    queue_req --> set_timeout (now) --> mod_delayed_work(,, delay=1)
+
+We actually do realize that the timeout should be zero, but the code
+forces it to a minimum of one jiffie.
+
+Using one jiffie as the minimum delay value results in sub-optimal
+scheduling of executing this work item by the workqueue, which on the
+below testbed costs about 3-4ms out of 12ms total time.
+
+To fix that, we let the minimum delay to be zero.  Note that the
+connect step times change too, as there are address resolution calls
+from that flow.
+
+The results were taken from running both client and server on the
+same node, over mlx4 RoCE port.
+
+before -->
+step              total ms     max ms     min us  us / conn
+create id    :        0.01       0.01       6.00       6.00
+resolve addr :        4.02       4.01    4013.00    4016.00
+resolve route:        0.18       0.18     182.00     183.00
+create qp    :        1.15       1.15    1150.00    1150.00
+connect      :        6.73       6.73    6730.00    6731.00
+disconnect   :        0.55       0.55     549.00     550.00
+destroy      :        0.01       0.01       9.00       9.00
+
+after -->
+step              total ms     max ms     min us  us / conn
+create id    :        0.01       0.01       6.00       6.00
+resolve addr :        0.05       0.05      49.00      52.00
+resolve route:        0.21       0.21     207.00     208.00
+create qp    :        1.10       1.10    1104.00    1104.00
+connect      :        1.22       1.22    1220.00    1221.00
+disconnect   :        0.71       0.71     713.00     713.00
+destroy      :        0.01       0.01       9.00       9.00
+
+Signed-off-by: Or Kehati <ork@mellanox.com>
+Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
+Acked-by: Sean Hefty <sean.hefty@intel.com>
+Signed-off-by: Roland Dreier <roland@purestorage.com>
+---
+ drivers/infiniband/core/addr.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
+index 8172d37..f80da50 100644
+--- a/drivers/infiniband/core/addr.c
++++ b/drivers/infiniband/core/addr.c
+@@ -176,8 +176,8 @@ static void set_timeout(unsigned long time)
+       unsigned long delay;
+       delay = time - jiffies;
+-      if ((long)delay <= 0)
+-              delay = 1;
++      if ((long)delay < 0)
++              delay = 0;
+       mod_delayed_work(addr_wq, &work, delay);
+ }
+-- 
+1.8.3.1
+
diff --git a/linux-next-cherry-picks/0015-IB-core-don-t-disallow-registering-region-starting-a.patch b/linux-next-cherry-picks/0015-IB-core-don-t-disallow-registering-region-starting-a.patch
new file mode 100644 (file)
index 0000000..d5cf8d5
--- /dev/null
@@ -0,0 +1,55 @@
+From 66578b0b2f69659f00b6169e6fe7377c4b100d18 Mon Sep 17 00:00:00 2001
+From: Yann Droneaud <ydroneaud@opteya.com>
+Date: Mon, 13 Apr 2015 14:56:23 +0200
+Subject: [PATCH] IB/core: don't disallow registering region starting at 0x0
+
+In a call to ib_umem_get(), if address is 0x0 and size is
+already page aligned, check added in commit 8494057ab5e4
+("IB/uverbs: Prevent integer overflow in ib_umem_get address
+arithmetic") will refuse to register a memory region that
+could otherwise be valid (provided vm.mmap_min_addr sysctl
+and mmap_low_allowed SELinux knobs allow userspace to map
+something at address 0x0).
+
+This patch allows back such registration: ib_umem_get()
+should probably don't care of the base address provided it
+can be pinned with get_user_pages().
+
+There's two possible overflows, in (addr + size) and in
+PAGE_ALIGN(addr + size), this patch keep ensuring none
+of them happen while allowing to pin memory at address
+0x0. Anyway, the case of size equal 0 is no more (partially)
+handled as 0-length memory region are disallowed by an
+earlier check.
+
+Link: http://mid.gmane.org/cover.1428929103.git.ydroneaud@opteya.com
+Cc: <stable@vger.kernel.org> # 8494057ab5e4 ("IB/uverbs: Prevent integer overflow in ib_umem_get address arithmetic")
+Cc: Shachar Raindel <raindel@mellanox.com>
+Cc: Jack Morgenstein <jackm@mellanox.com>
+Cc: Or Gerlitz <ogerlitz@mellanox.com>
+Signed-off-by: Yann Droneaud <ydroneaud@opteya.com>
+Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
+Reviewed-by: Haggai Eran <haggaie@mellanox.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+---
+ drivers/infiniband/core/umem.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
+index 9ac4068..38acb3c 100644
+--- a/drivers/infiniband/core/umem.c
++++ b/drivers/infiniband/core/umem.c
+@@ -106,8 +106,8 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
+        * If the combination of the addr and size requested for this memory
+        * region causes an integer overflow, return error.
+        */
+-      if ((PAGE_ALIGN(addr + size) <= size) ||
+-          (PAGE_ALIGN(addr + size) <= addr))
++      if (((addr + size) < addr) ||
++          PAGE_ALIGN(addr + size) < (addr + size))
+               return ERR_PTR(-EINVAL);
+       if (!can_do_mlock())
+-- 
+1.8.3.1
+
diff --git a/linux-next-cherry-picks/0016-ib_uverbs-Fix-pages-leak-when-using-XRC-SRQs.patch b/linux-next-cherry-picks/0016-ib_uverbs-Fix-pages-leak-when-using-XRC-SRQs.patch
new file mode 100644 (file)
index 0000000..af68e52
--- /dev/null
@@ -0,0 +1,69 @@
+From a233c4b54c882817ae9dd73384d5dd75d3e57498 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?S=C3=A9bastien=20Dugu=C3=A9?= <sebastien.dugue@atos.net>
+Date: Thu, 9 Apr 2015 11:13:41 +0200
+Subject: [PATCH] ib_uverbs: Fix pages leak when using XRC SRQs
+
+Hello,
+
+  When an application using XRCs abruptly terminates, the mmaped pages
+of the CQ buffers are leaked.
+
+  This comes from the fact that when resources are released in
+ib_uverbs_cleanup_ucontext(), we fail to release the CQs because their
+refcount is not 0.
+
+  When creating an XRC SRQ, we increment the associated CQ refcount.
+This refcount is only decremented when the SRQ is released.
+
+  Therefore we need to release the SRQs prior to the CQs to make sure
+that all references to the CQs are gone before trying to release these.
+
+Signed-off-by: Sebastien Dugue <sebastien.dugue@bull.net>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+---
+ drivers/infiniband/core/uverbs_main.c | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
+index 259dcc7..88cce9b 100644
+--- a/drivers/infiniband/core/uverbs_main.c
++++ b/drivers/infiniband/core/uverbs_main.c
+@@ -246,6 +246,17 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
+               kfree(uqp);
+       }
++      list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
++              struct ib_srq *srq = uobj->object;
++              struct ib_uevent_object *uevent =
++                      container_of(uobj, struct ib_uevent_object, uobject);
++
++              idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
++              ib_destroy_srq(srq);
++              ib_uverbs_release_uevent(file, uevent);
++              kfree(uevent);
++      }
++
+       list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
+               struct ib_cq *cq = uobj->object;
+               struct ib_uverbs_event_file *ev_file = cq->cq_context;
+@@ -258,17 +269,6 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
+               kfree(ucq);
+       }
+-      list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
+-              struct ib_srq *srq = uobj->object;
+-              struct ib_uevent_object *uevent =
+-                      container_of(uobj, struct ib_uevent_object, uobject);
+-
+-              idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
+-              ib_destroy_srq(srq);
+-              ib_uverbs_release_uevent(file, uevent);
+-              kfree(uevent);
+-      }
+-
+       list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
+               struct ib_mr *mr = uobj->object;
+-- 
+1.8.3.1
+
diff --git a/linux-next-cherry-picks/0017-IB-core-Fix-unaligned-accesses.patch b/linux-next-cherry-picks/0017-IB-core-Fix-unaligned-accesses.patch
new file mode 100644 (file)
index 0000000..8987789
--- /dev/null
@@ -0,0 +1,142 @@
+From 0d0f738f6a11856a704dcd8fd3a008b200f17625 Mon Sep 17 00:00:00 2001
+From: David Ahern <david.ahern@oracle.com>
+Date: Sun, 3 May 2015 09:48:26 -0400
+Subject: [PATCH] IB/core: Fix unaligned accesses
+
+Addresses the following kernel logs seen during boot of sparc systems:
+
+Kernel unaligned access at TPC[103bce50] cm_find_listen+0x34/0xf8 [ib_cm]
+Kernel unaligned access at TPC[103bce50] cm_find_listen+0x34/0xf8 [ib_cm]
+Kernel unaligned access at TPC[103bce50] cm_find_listen+0x34/0xf8 [ib_cm]
+Kernel unaligned access at TPC[103bce50] cm_find_listen+0x34/0xf8 [ib_cm]
+Kernel unaligned access at TPC[103bce50] cm_find_listen+0x34/0xf8 [ib_cm]
+
+Signed-off-by: David Ahern <david.ahern@oracle.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+---
+ drivers/infiniband/core/cm.c      | 23 +++++++++++------------
+ drivers/infiniband/core/cm_msgs.h |  4 ++--
+ include/rdma/ib_cm.h              |  7 ++++---
+ 3 files changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
+index e28a494..0c14191 100644
+--- a/drivers/infiniband/core/cm.c
++++ b/drivers/infiniband/core/cm.c
+@@ -437,39 +437,38 @@ static struct cm_id_private * cm_acquire_id(__be32 local_id, __be32 remote_id)
+       return cm_id_priv;
+ }
+-static void cm_mask_copy(u8 *dst, u8 *src, u8 *mask)
++static void cm_mask_copy(u32 *dst, const u32 *src, const u32 *mask)
+ {
+       int i;
+-      for (i = 0; i < IB_CM_COMPARE_SIZE / sizeof(unsigned long); i++)
+-              ((unsigned long *) dst)[i] = ((unsigned long *) src)[i] &
+-                                           ((unsigned long *) mask)[i];
++      for (i = 0; i < IB_CM_COMPARE_SIZE; i++)
++              dst[i] = src[i] & mask[i];
+ }
+ static int cm_compare_data(struct ib_cm_compare_data *src_data,
+                          struct ib_cm_compare_data *dst_data)
+ {
+-      u8 src[IB_CM_COMPARE_SIZE];
+-      u8 dst[IB_CM_COMPARE_SIZE];
++      u32 src[IB_CM_COMPARE_SIZE];
++      u32 dst[IB_CM_COMPARE_SIZE];
+       if (!src_data || !dst_data)
+               return 0;
+       cm_mask_copy(src, src_data->data, dst_data->mask);
+       cm_mask_copy(dst, dst_data->data, src_data->mask);
+-      return memcmp(src, dst, IB_CM_COMPARE_SIZE);
++      return memcmp(src, dst, sizeof(src));
+ }
+-static int cm_compare_private_data(u8 *private_data,
++static int cm_compare_private_data(u32 *private_data,
+                                  struct ib_cm_compare_data *dst_data)
+ {
+-      u8 src[IB_CM_COMPARE_SIZE];
++      u32 src[IB_CM_COMPARE_SIZE];
+       if (!dst_data)
+               return 0;
+       cm_mask_copy(src, private_data, dst_data->mask);
+-      return memcmp(src, dst_data->data, IB_CM_COMPARE_SIZE);
++      return memcmp(src, dst_data->data, sizeof(src));
+ }
+ /*
+@@ -538,7 +537,7 @@ static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
+ static struct cm_id_private * cm_find_listen(struct ib_device *device,
+                                            __be64 service_id,
+-                                           u8 *private_data)
++                                           u32 *private_data)
+ {
+       struct rb_node *node = cm.listen_service_table.rb_node;
+       struct cm_id_private *cm_id_priv;
+@@ -953,7 +952,7 @@ int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask,
+               cm_mask_copy(cm_id_priv->compare_data->data,
+                            compare_data->data, compare_data->mask);
+               memcpy(cm_id_priv->compare_data->mask, compare_data->mask,
+-                     IB_CM_COMPARE_SIZE);
++                     sizeof(compare_data->mask));
+       }
+       cm_id->state = IB_CM_LISTEN;
+diff --git a/drivers/infiniband/core/cm_msgs.h b/drivers/infiniband/core/cm_msgs.h
+index be068f4..8b76f0e 100644
+--- a/drivers/infiniband/core/cm_msgs.h
++++ b/drivers/infiniband/core/cm_msgs.h
+@@ -103,7 +103,7 @@ struct cm_req_msg {
+       /* local ACK timeout:5, rsvd:3 */
+       u8 alt_offset139;
+-      u8 private_data[IB_CM_REQ_PRIVATE_DATA_SIZE];
++      u32 private_data[IB_CM_REQ_PRIVATE_DATA_SIZE / sizeof(u32)];
+ } __attribute__ ((packed));
+@@ -801,7 +801,7 @@ struct cm_sidr_req_msg {
+       __be16 rsvd;
+       __be64 service_id;
+-      u8 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE];
++      u32 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE / sizeof(u32)];
+ } __attribute__ ((packed));
+ struct cm_sidr_rep_msg {
+diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h
+index 0e3ff30..39ed2d2 100644
+--- a/include/rdma/ib_cm.h
++++ b/include/rdma/ib_cm.h
+@@ -105,7 +105,8 @@ enum ib_cm_data_size {
+       IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE = 216,
+       IB_CM_SIDR_REP_PRIVATE_DATA_SIZE = 136,
+       IB_CM_SIDR_REP_INFO_LENGTH       = 72,
+-      IB_CM_COMPARE_SIZE               = 64
++      /* compare done u32 at a time */
++      IB_CM_COMPARE_SIZE               = (64 / sizeof(u32))
+ };
+ struct ib_cm_id;
+@@ -337,8 +338,8 @@ void ib_destroy_cm_id(struct ib_cm_id *cm_id);
+ #define IB_SDP_SERVICE_ID_MASK        cpu_to_be64(0xFFFFFFFFFFFF0000ULL)
+ struct ib_cm_compare_data {
+-      u8  data[IB_CM_COMPARE_SIZE];
+-      u8  mask[IB_CM_COMPARE_SIZE];
++      u32  data[IB_CM_COMPARE_SIZE];
++      u32  mask[IB_CM_COMPARE_SIZE];
+ };
+ /**
+-- 
+1.8.3.1
+