[PATCH 1/5] IB/core: introduce an IB device pool

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

 



Logic for caching ib_device,ib_pd pair by node_guid is used for nvme,
nvmet, iser and isert.  Make a common functionality out of that.

Signed-off-by: Roman Pen <roman.penyaev@xxxxxxxxxxxxxxxx>
Cc: Christoph Hellwig <hch@xxxxxx>
Cc: Steve Wise <swise@xxxxxxxxxxxxxxxxxxxxx>
Cc: Bart Van Assche <bart.vanassche@xxxxxxxxxxx>
Cc: Sagi Grimberg <sagi@xxxxxxxxxxx>
Cc: Doug Ledford <dledford@xxxxxxxxxx>
---
 drivers/infiniband/core/Makefile   |   2 +-
 drivers/infiniband/core/dev_pool.c | 136 +++++++++++++++++++++++++++++++++++++
 include/rdma/dev_pool.h            |  62 +++++++++++++++++
 3 files changed, 199 insertions(+), 1 deletion(-)
 create mode 100644 drivers/infiniband/core/dev_pool.c
 create mode 100644 include/rdma/dev_pool.h

diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index dda9e856e3fa..8068c641e48d 100644
--- a/drivers/infiniband/core/Makefile
+++ b/drivers/infiniband/core/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_INFINIBAND_USER_ACCESS) +=	ib_uverbs.o ib_ucm.o \
 					$(user_access-y)
 
 ib_core-y :=			packer.o ud_header.o verbs.o cq.o rw.o sysfs.o \
-				device.o fmr_pool.o cache.o netlink.o \
+				device.o fmr_pool.o cache.o netlink.o dev_pool.o \
 				roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \
 				multicast.o mad.o smi.o agent.o mad_rmpp.o \
 				security.o nldev.o restrack.o
diff --git a/drivers/infiniband/core/dev_pool.c b/drivers/infiniband/core/dev_pool.c
new file mode 100644
index 000000000000..641c8ad45590
--- /dev/null
+++ b/drivers/infiniband/core/dev_pool.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2018 ProfitBricks GmbH.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <rdma/dev_pool.h>
+
+void ib_pool_dev_init(enum ib_pd_flags pd_flags,
+		      struct ib_pool_device *(*alloc)(void),
+		      void (*free)(struct ib_pool_device *),
+		      int (*init)(struct ib_pool_device *),
+		      struct ib_device_pool *pool)
+{
+	INIT_LIST_HEAD(&pool->list);
+	mutex_init(&pool->mutex);
+
+	pool->pd_flags = pd_flags;
+
+	BUG_ON(!alloc ^ !free);
+	pool->alloc = alloc;
+	pool->free = free;
+	pool->init = init;
+}
+EXPORT_SYMBOL(ib_pool_dev_init);
+
+void ib_pool_dev_deinit(struct ib_device_pool *pool)
+{
+	WARN_ON(!list_empty(&pool->list));
+}
+EXPORT_SYMBOL(ib_pool_dev_deinit);
+
+static void dev_free(struct kref *ref)
+{
+	struct ib_pool_device *dev;
+	struct ib_device_pool *pool;
+	struct ib_pd *ib_pd;
+
+	dev = container_of(ref, typeof(*dev), ref);
+	pool = dev->pool;
+
+	mutex_lock(&pool->mutex);
+	list_del(&dev->entry);
+	mutex_unlock(&pool->mutex);
+
+	ib_pd = dev->ib_pd;
+	if (pool->free)
+		pool->free(dev);
+	else
+		kfree(dev);
+
+	ib_dealloc_pd(ib_pd);
+}
+
+int ib_pool_dev_put(struct ib_pool_device *dev)
+{
+	return kref_put(&dev->ref, dev_free);
+}
+EXPORT_SYMBOL(ib_pool_dev_put);
+
+int ib_pool_dev_get(struct ib_pool_device *dev)
+{
+	return kref_get_unless_zero(&dev->ref);
+}
+EXPORT_SYMBOL(ib_pool_dev_get);
+
+bool ib_pool_dev_exists(struct ib_device *ib_dev,
+			struct ib_device_pool *pool)
+{
+	struct ib_pool_device *dev;
+	bool found = false;
+
+	mutex_lock(&pool->mutex);
+	list_for_each_entry(dev, &pool->list, entry) {
+		if (dev->ib_dev == ib_dev) {
+			found = true;
+			break;
+		}
+	}
+	mutex_unlock(&pool->mutex);
+
+	return false;
+}
+EXPORT_SYMBOL(ib_pool_dev_exists);
+
+struct ib_pool_device *
+ib_pool_dev_find_get_or_create(struct ib_device *ib_dev,
+			       struct ib_device_pool *pool)
+{
+	struct ib_pool_device *dev;
+
+	mutex_lock(&pool->mutex);
+	list_for_each_entry(dev, &pool->list, entry) {
+		if (dev->ib_dev->node_guid == ib_dev->node_guid &&
+		    ib_pool_dev_get(dev))
+			goto out_unlock;
+	}
+	if (pool->alloc)
+		dev = pool->alloc();
+	else
+		dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (unlikely(IS_ERR_OR_NULL(dev)))
+		goto out_err;
+
+	kref_init(&dev->ref);
+	dev->pool = pool;
+	dev->ib_dev = ib_dev;
+	dev->ib_pd = ib_alloc_pd(ib_dev, pool->pd_flags);
+	if (unlikely(IS_ERR(dev->ib_pd)))
+		goto out_free_dev;
+
+	if (pool->init && pool->init(dev))
+		goto out_free_pd;
+
+	list_add(&dev->entry, &pool->list);
+out_unlock:
+	mutex_unlock(&pool->mutex);
+	return dev;
+
+out_free_pd:
+	ib_dealloc_pd(dev->ib_pd);
+out_free_dev:
+	pool->free ? pool->free(dev) : kfree(dev);
+out_err:
+	mutex_unlock(&pool->mutex);
+	return NULL;
+}
+EXPORT_SYMBOL(ib_pool_dev_find_get_or_create);
diff --git a/include/rdma/dev_pool.h b/include/rdma/dev_pool.h
new file mode 100644
index 000000000000..74fd27b8ed25
--- /dev/null
+++ b/include/rdma/dev_pool.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2018 ProfitBricks GmbH.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DEV_POOL__
+#define __DEV_POOL__
+
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+#include <rdma/rdma_cm.h>
+
+struct ib_pool_device;
+
+struct ib_device_pool {
+	struct mutex		mutex;
+	struct list_head	list;
+
+	enum ib_pd_flags	pd_flags;
+
+	struct ib_pool_device *(*alloc)(void);
+	void (*free)(struct ib_pool_device *);
+	int (*init)(struct ib_pool_device *);
+};
+
+struct ib_pool_device {
+	struct ib_device	*ib_dev;
+	struct ib_pd		*ib_pd;
+	struct kref		ref;
+	struct list_head	entry;
+	struct ib_device_pool	*pool;
+};
+
+void ib_pool_dev_init(enum ib_pd_flags pd_flags,
+		      struct ib_pool_device *(*alloc)(void),
+		      void (*free)(struct ib_pool_device *),
+		      int (*init)(struct ib_pool_device *),
+		      struct ib_device_pool *pool);
+
+void ib_pool_dev_deinit(struct ib_device_pool *pool);
+
+struct ib_pool_device *
+ib_pool_dev_find_get_or_create(struct ib_device *ib_dev,
+			       struct ib_device_pool *pool);
+
+bool ib_pool_dev_exists(struct ib_device *ib_dev,
+			struct ib_device_pool *pool);
+
+int ib_pool_dev_get(struct ib_pool_device *dev);
+int ib_pool_dev_put(struct ib_pool_device *dev);
+
+#endif /* __DEV_POOL__ */
-- 
2.13.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[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