[PATCH for-rc] IB/cma: Fix false P_Key mismatch messages

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



There are three conditions that must be fulfilled in order to consider
a partition match. Those are:

      1. Both P_Keys must valid
      2. At least one must be a full member
      3. The partitions (lower 15 bits) must match

In system employing both limited and full membership ports, we see
these false warning messages:

RDMA CMA: got different BTH P_Key (0x2a00) and primary path P_Key (0xaa00)
RDMA CMA: in the future this may cause the request to be dropped

even though the partition is the same.

See IBTA 10.9.1.2 Special P_Keys and 10.9.3 Partition Key Matching for
a reference.

Fixes: 84424a7fc793 ("IB/cma: Print warning on different inner and header P_Keys")
Signed-off-by: Håkon Bugge <haakon.bugge@xxxxxxxxxx>
---
 drivers/infiniband/core/cma.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 2b9ffc2..f5bcf7d 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -1368,6 +1368,24 @@ static int cma_save_net_info(struct sockaddr *src_addr,
 	return cma_save_ip_info(src_addr, dst_addr, ib_event, service_id);
 }
 
+/*
+ * If at least one of the pkeys is a full member, none of them are
+ * invalid, and the partitions (lower 15 bits) are equal, we have a
+ * match.
+ *
+ * See IBTA 10.9.1.2 Special P_Keys and 10.9.3 Partition Key Matching
+ */
+
+static bool partition_match(u16 pkey_a, u16 pkey_b)
+{
+	const u16 fmb = 0x8000; /* Full Member Bit */
+	const bool valid_pkeys = (pkey_a & ~fmb) && (pkey_b & ~fmb);
+	const bool one_full = (pkey_a | pkey_b) & fmb;
+	const bool same_partition = (pkey_a | fmb) == (pkey_b | fmb);
+
+	return valid_pkeys && one_full && same_partition;
+}
+
 static int cma_save_req_info(const struct ib_cm_event *ib_event,
 			     struct cma_req_info *req)
 {
@@ -1385,7 +1403,7 @@ static int cma_save_req_info(const struct ib_cm_event *ib_event,
 		req->has_gid	= true;
 		req->service_id = req_param->primary_path->service_id;
 		req->pkey	= be16_to_cpu(req_param->primary_path->pkey);
-		if (req->pkey != req_param->bth_pkey)
+		if (!partition_match(req->pkey, req_param->bth_pkey))
 			pr_warn_ratelimited("RDMA CMA: got different BTH P_Key (0x%x) and primary path P_Key (0x%x)\n"
 					    "RDMA CMA: in the future this may cause the request to be dropped\n",
 					    req_param->bth_pkey, req->pkey);
@@ -1396,7 +1414,7 @@ static int cma_save_req_info(const struct ib_cm_event *ib_event,
 		req->has_gid	= false;
 		req->service_id	= sidr_param->service_id;
 		req->pkey	= sidr_param->pkey;
-		if (req->pkey != sidr_param->bth_pkey)
+		if (!partition_match(req->pkey, sidr_param->bth_pkey))
 			pr_warn_ratelimited("RDMA CMA: got different BTH P_Key (0x%x) and SIDR request payload P_Key (0x%x)\n"
 					    "RDMA CMA: in the future this may cause the request to be dropped\n",
 					    sidr_param->bth_pkey, req->pkey);
-- 
1.8.3.1




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux