Blob Blame History Raw
From 2f6e9cb2087508d29bf525f652136ea23a007bc6 Mon Sep 17 00:00:00 2001
From: Honggang Li <honli@redhat.com>
Date: Fri, 7 Feb 2020 10:25:31 +0800
Subject: [PATCH] ibacm: Do not open non InfiniBand device

For dual port HCA, which has an InfiniBand port and an Ethernet port,
only open InfiniBand port will introduce segment fault issues.

Because the Ethernet port did not open yet, segment fault when active
the Ethernet port. The second segment fault issue happens when there
is asyn event on the Ethernet port.

We should skip pure iWARP or RoCE devices, but not device which has at
least one InfiniBand port.

Fixes: e9ffc0b3b940 ("ibacm: only open InfiniBand port")
Signed-off-by: Honggang Li <honli@redhat.com>
---
 ibacm/src/acm.c | 47 ++++++++++++++++++++++++++---------------------
 1 file changed, 26 insertions(+), 21 deletions(-)

diff --git a/ibacm/src/acm.c b/ibacm/src/acm.c
index ad313075c7bb..283620338c9d 100644
--- a/ibacm/src/acm.c
+++ b/ibacm/src/acm.c
@@ -2604,7 +2604,7 @@ static void acm_open_dev(struct ibv_device *ibdev)
 	struct ibv_context *verbs;
 	size_t size;
 	int i, ret;
-	unsigned int opened_ib_port_cnt = 0;
+	bool has_ib_port = false;
 
 	acm_log(1, "%s\n", ibdev->name);
 	verbs = ibv_open_device(ibdev);
@@ -2619,6 +2619,27 @@ static void acm_open_dev(struct ibv_device *ibdev)
 		goto err1;
 	}
 
+	for (i = 0; i < attr.phys_port_cnt; i++) {
+		ret = ibv_query_port(verbs, i + 1, &port_attr);
+		if (ret) {
+			acm_log(0, "ERROR - ibv_query_port (%s, %d) return (%d)\n",
+				ibdev->name, i + 1, ret);
+			continue;
+		}
+
+		if (port_attr.link_layer == IBV_LINK_LAYER_INFINIBAND) {
+			acm_log(1, "%s port %d is an InfiniBand port\n", ibdev->name, i + 1);
+			has_ib_port = true;
+		} else {
+			acm_log(1, "%s port %d is not an InfiniBand port\n", ibdev->name, i + 1);
+		}
+	}
+
+	if (!has_ib_port) {
+		acm_log(1, "%s does not support InfiniBand.\n", ibdev->name);
+		goto err1;
+	}
+
 	size = sizeof(*dev) + sizeof(struct acmc_port) * attr.phys_port_cnt;
 	dev = (struct acmc_device *) calloc(1, size);
 	if (!dev)
@@ -2630,29 +2651,13 @@ static void acm_open_dev(struct ibv_device *ibdev)
 	list_head_init(&dev->prov_dev_context_list);
 
 	for (i = 0; i < dev->port_cnt; i++) {
-		acm_log(1, "%s port %d\n", ibdev->name, i + 1);
-		ret = ibv_query_port(dev->device.verbs, i + 1, &port_attr);
-		if (ret) {
-			acm_log(0, "ERROR - ibv_query_port (%d)\n", ret);
-			continue;
-		}
-		if (port_attr.link_layer != IBV_LINK_LAYER_INFINIBAND) {
-			acm_log(1, "not an InfiniBand port\n");
-			continue;
-		}
-
 		acm_open_port(&dev->port[i], dev, i + 1);
-		opened_ib_port_cnt++;
 	}
 
-	if (opened_ib_port_cnt) {
-		list_add(&dev_list, &dev->entry);
-		acm_log(1, "%d InfiniBand %s opened for %s\n",
-				opened_ib_port_cnt,
-				opened_ib_port_cnt == 1 ? "port" : "ports",
-				ibdev->name);
-		return;
-	}
+	list_add(&dev_list, &dev->entry);
+
+	acm_log(1, "%s opened\n", ibdev->name);
+	return;
 
 err1:
 	ibv_close_device(verbs);
-- 
2.24.1