Subject: [PATCH rdma-next 4/8] IB/core: Skip device which doesn't have necessary capabilities

From: Leon Romanovsky <[email-masked]>
Date: Mon, 5 Apr 2021 08:49:56 +0300

From: Parav Pandit <[email-masked]>

If device doesn't have multicast capability, avoid client registration
for it. This saves 16Kbytes of memory for a RDMA device consist of 128
ports.

If device doesn't support subnet administration, avoid client
registration for it. This saves 8Kbytes of memory for a RDMA device
consist of 128 ports.

Signed-off-by: Parav Pandit <[email-masked]>
Signed-off-by: Leon Romanovsky <[email-masked]>
---
 drivers/infiniband/core/multicast.c | 15 ++++++++++++++-
 drivers/infiniband/core/sa_query.c  | 15 ++++++++++++++-
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index a5dd4b7a74bc..8c81acc24e3e 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -44,11 +44,13 @@
 
 static int mcast_add_one(struct ib_device *device);
 static void mcast_remove_one(struct ib_device *device, void *client_data);
+static bool mcast_client_supported(struct ib_device *device);
 
 static struct ib_client mcast_client = {
 	.name   = "ib_multicast",
 	.add    = mcast_add_one,
-	.remove = mcast_remove_one
+	.remove = mcast_remove_one,
+	.is_supported = mcast_client_supported,
 };
 
 static struct ib_sa_client	sa_client;
@@ -816,6 +818,17 @@ static void mcast_event_handler(struct ib_event_handler *handler,
 	}
 }
 
+static bool mcast_client_supported(struct ib_device *device)
+{
+	u32 i;
+
+	rdma_for_each_port(device, i) {
+		if (rdma_cap_ib_mcast(device, i))
+			return true;
+	}
+	return false;
+}
+
 static int mcast_add_one(struct ib_device *device)
 {
 	struct mcast_device *dev;
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 9a4a49c37922..7e00e24d9423 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -176,11 +176,13 @@ static const struct nla_policy ib_nl_policy[LS_NLA_TYPE_MAX] = {
 
 static int ib_sa_add_one(struct ib_device *device);
 static void ib_sa_remove_one(struct ib_device *device, void *client_data);
+static bool ib_sa_client_supported(struct ib_device *device);
 
 static struct ib_client sa_client = {
 	.name   = "sa",
 	.add    = ib_sa_add_one,
-	.remove = ib_sa_remove_one
+	.remove = ib_sa_remove_one,
+	.is_supported = ib_sa_client_supported,
 };
 
 static DEFINE_XARRAY_FLAGS(queries, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
@@ -2293,6 +2295,17 @@ static void ib_sa_event(struct ib_event_handler *handler,
 	}
 }
 
+static bool ib_sa_client_supported(struct ib_device *device)
+{
+	unsigned int i;
+
+	rdma_for_each_port(device, i) {
+		if (rdma_cap_ib_sa(device, i))
+			return true;
+	}
+	return false;
+}
+
 static int ib_sa_add_one(struct ib_device *device)
 {
 	struct ib_sa_device *sa_dev;
-- 
2.30.2