[PATCH rdma-next v2 03/10] RDMA/core: Introduce ib_core_device to hold device

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

 



From: Parav Pandit <parav@xxxxxxxxxxxx>

In order to support sysfs entries in multiple net namespaces for a rdma
device, introduce a ib_core_device whose scope is limited to hold core
device and per port sysfs related entires.

This is preparation patch so that multiple ib_core_devices in each net
namespace can be created in subsequent patch who all can share
ib_device.

(a) Move sysfs specific fields to ib_core_device.
(b) Make sysfs and device life cycle related routines to work on
ib_core_device.
(c) Introduce and use rdma_init_coredev() helper to initialize
coredev fields.
(d) Do not access driver data which is supposed to be used by the
provider driver.

Signed-off-by: Parav Pandit <parav@xxxxxxxxxxxx>
Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx>
---
 drivers/infiniband/core/core_priv.h |  2 ++
 drivers/infiniband/core/device.c    | 28 ++++++++++++++++------
 drivers/infiniband/core/sysfs.c     | 36 ++++++++++++++---------------
 include/rdma/ib_verbs.h             | 24 +++++++++++++++----
 4 files changed, 60 insertions(+), 30 deletions(-)

diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index cc7535c5e192..0da0a26c02b9 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -54,6 +54,8 @@ struct pkey_index_qp_list {
 	struct list_head    qp_list;
 };
 
+extern const struct attribute_group ib_dev_attr_group;
+
 int  ib_device_register_sysfs(struct ib_device *device,
 			      int (*port_callback)(struct ib_device *,
 						   u8, struct kobject *));
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 0027b0d79b09..16e1e854a3b4 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -269,6 +269,24 @@ static struct class ib_class = {
 	.dev_uevent = ib_device_uevent,
 };
 
+static void rdma_init_coredev(struct ib_core_device *coredev,
+			      struct ib_device *dev)
+{
+	/* This BUILD_BUG_ON is intended to catch layout change
+	 * of union of ib_core_device and device.
+	 * dev must be the first element as ib_core and providers
+	 * driver uses it. Adding anything in ib_core_device before
+	 * device will break this assumption.
+	 */
+	BUILD_BUG_ON(offsetof(struct ib_core_device, dev) != 0);
+
+	coredev->dev.class = &ib_class;
+	coredev->dev.groups = dev->groups;
+	device_initialize(&coredev->dev);
+	coredev->owner = dev;
+	INIT_LIST_HEAD(&coredev->port_list);
+}
+
 /**
  * ib_alloc_device - allocate an IB device struct
  * @size:size of structure to allocate
@@ -290,20 +308,16 @@ struct ib_device *ib_alloc_device(size_t size)
 	if (!device)
 		return NULL;
 
-	rdma_restrack_init(&device->res);
-
-	device->dev.class = &ib_class;
-	device_initialize(&device->dev);
-
-	dev_set_drvdata(&device->dev, device);
+	device->groups[0] = &ib_dev_attr_group;
+	rdma_init_coredev(&device->coredev, device);
 
 	INIT_LIST_HEAD(&device->event_handler_list);
 	spin_lock_init(&device->event_handler_lock);
 	rwlock_init(&device->client_data_lock);
 	INIT_LIST_HEAD(&device->client_data_list);
-	INIT_LIST_HEAD(&device->port_list);
 	refcount_set(&device->refcount, 1);
 	init_completion(&device->unreg_completion);
+	rdma_restrack_init(&device->res);
 
 	return device;
 }
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index da4fafb28867..486219cc5ac4 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -1015,10 +1015,11 @@ static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
 	return;
 }
 
-static int add_port(struct ib_device *device, int port_num,
+static int add_port(struct ib_core_device *coredev, int port_num,
 		    int (*port_callback)(struct ib_device *,
 					 u8, struct kobject *))
 {
+	struct ib_device *device = rdma_device_to_ibdev(&coredev->dev);
 	struct ib_port *p;
 	struct ib_port_attr attr;
 	int i;
@@ -1036,7 +1037,7 @@ static int add_port(struct ib_device *device, int port_num,
 	p->port_num   = port_num;
 
 	ret = kobject_init_and_add(&p->kobj, &port_type,
-				   device->ports_kobj,
+				   coredev->ports_kobj,
 				   "%d", port_num);
 	if (ret) {
 		kfree(p);
@@ -1127,7 +1128,7 @@ static int add_port(struct ib_device *device, int port_num,
 	if (device->alloc_hw_stats && port_num)
 		setup_hw_stats(device, p, port_num);
 
-	list_add_tail(&p->kobj.entry, &device->port_list);
+	list_add_tail(&p->kobj.entry, &coredev->port_list);
 
 	kobject_uevent(&p->kobj, KOBJ_ADD);
 	return 0;
@@ -1277,15 +1278,15 @@ static struct attribute *ib_dev_attrs[] = {
 	NULL,
 };
 
-static const struct attribute_group dev_attr_group = {
+const struct attribute_group ib_dev_attr_group = {
 	.attrs = ib_dev_attrs,
 };
 
-static void ib_free_port_attrs(struct ib_device *device)
+static void ib_free_port_attrs(struct ib_core_device *coredev)
 {
 	struct kobject *p, *t;
 
-	list_for_each_entry_safe(p, t, &device->port_list, entry) {
+	list_for_each_entry_safe(p, t, &coredev->port_list, entry) {
 		struct ib_port *port = container_of(p, struct ib_port, kobj);
 
 		list_del(&p->entry);
@@ -1305,27 +1306,29 @@ static void ib_free_port_attrs(struct ib_device *device)
 		kobject_put(p);
 	}
 
-	kobject_put(device->ports_kobj);
+	kobject_put(coredev->ports_kobj);
 }
 
-static int ib_setup_port_attrs(struct ib_device *device,
+static int ib_setup_port_attrs(struct ib_core_device *coredev,
 			       int (*port_callback)(struct ib_device *,
 						    u8, struct kobject *))
 {
+	struct ib_device *device = rdma_device_to_ibdev(&coredev->dev);
 	int ret;
 	int i;
 
-	device->ports_kobj = kobject_create_and_add("ports", &device->dev.kobj);
-	if (!device->ports_kobj)
+	coredev->ports_kobj = kobject_create_and_add("ports",
+						     &coredev->dev.kobj);
+	if (!coredev->ports_kobj)
 		return -ENOMEM;
 
 	if (rdma_cap_ib_switch(device)) {
-		ret = add_port(device, 0, port_callback);
+		ret = add_port(coredev, 0, port_callback);
 		if (ret)
 			goto err_put;
 	} else {
 		for (i = 1; i <= device->phys_port_cnt; ++i) {
-			ret = add_port(device, i, port_callback);
+			ret = add_port(coredev, i, port_callback);
 			if (ret)
 				goto err_put;
 		}
@@ -1334,7 +1337,7 @@ static int ib_setup_port_attrs(struct ib_device *device,
 	return 0;
 
 err_put:
-	ib_free_port_attrs(device);
+	ib_free_port_attrs(coredev);
 	return ret;
 }
 
@@ -1344,14 +1347,11 @@ int ib_device_register_sysfs(struct ib_device *device,
 {
 	int ret;
 
-	device->groups[0] = &dev_attr_group;
-	device->dev.groups = device->groups;
-
 	ret = device_add(&device->dev);
 	if (ret)
 		return ret;
 
-	ret = ib_setup_port_attrs(device, port_callback);
+	ret = ib_setup_port_attrs(&device->coredev, port_callback);
 	if (ret) {
 		device_del(&device->dev);
 		return ret;
@@ -1371,6 +1371,6 @@ void ib_device_unregister_sysfs(struct ib_device *device)
 		free_hsag(&device->dev.kobj, device->hw_stats_ag);
 	kfree(device->hw_stats);
 
-	ib_free_port_attrs(device);
+	ib_free_port_attrs(&device->coredev);
 	device_unregister(&device->dev);
 }
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 446143ed49ae..f9bedf28e292 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2257,6 +2257,16 @@ struct ib_counters_read_attr {
 
 struct uverbs_attr_bundle;
 
+struct ib_core_device {
+	/* device must be the first element in structure until,
+	 * union of ib_core_device and device exists in ib_device.
+	 */
+	struct device		dev;
+	struct kobject		*ports_kobj;
+	struct list_head	port_list;
+	struct ib_device	*owner;	/* reach back to owner ib_device */
+};
+
 struct ib_device {
 	/* Do not access @dma_device directly from ULP nor from HW drivers. */
 	struct device                *dma_device;
@@ -2553,16 +2563,17 @@ struct ib_device {
 				      struct rdma_netdev_alloc_params *params);
 
 	struct module               *owner;
-	struct device                dev;
+	union {
+		struct device		dev;
+		struct ib_core_device	coredev;
+	};
+
 	/* First group for device attributes,
 	 * Second group for driver provided attributes (optional).
 	 * It is NULL terminated array.
 	 */
 	const struct attribute_group	*groups[3];
 
-	struct kobject			*ports_kobj;
-	struct list_head             port_list;
-
 	enum {
 		IB_DEV_UNINITIALIZED,
 		IB_DEV_REGISTERED,
@@ -4262,7 +4273,10 @@ rdma_set_device_sysfs_group(struct ib_device *dev,
  */
 static inline struct ib_device *rdma_device_to_ibdev(struct device *device)
 {
-	return dev_get_drvdata(device);
+	struct ib_core_device *coredev =
+		container_of(device, struct ib_core_device, dev);
+
+	return coredev->owner;
 }
 
 /**
-- 
2.19.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