[openib-general] [PATCH] Basic driver model/sysfs support

Roland Dreier roland at topspin.com
Thu Sep 2 10:56:41 PDT 2004


This patch starts to add driver model/sysfs support.  It adds
ib_alloc_device/ib_dealloc_device so that the access layer can manage
reference counting of struct ib_device (and free the ib_device in the
driver model ->release() method).  It also creates a basic
"infiniband" class that devices belong to.

Next step is to add attributes to the device and start killing off
some of the info in /proc (and redundant ioctls).

 - Roland

Index: src/linux-kernel/infiniband/include/ib_verbs.h
===================================================================
--- src/linux-kernel/infiniband/include/ib_verbs.h	(revision 715)
+++ src/linux-kernel/infiniband/include/ib_verbs.h	(working copy)
@@ -593,7 +593,6 @@
 
 	char                          name[IB_DEVICE_NAME_MAX];
 	char                         *provider;
-	void                         *private;
 	struct list_head              core_list;
 	void                         *core;
 	void                         *mad;
@@ -691,9 +690,20 @@
 
 	struct class_device          class_dev;
 
+	enum {
+		IB_DEV_UNINITIALIZED,
+		IB_DEV_REGISTERED,
+		IB_DEV_UNREGISTERED
+	}                            reg_state;
+
 	u8                           node_type;
 };
 
+struct ib_device *ib_alloc_device(size_t size);
+void ib_dealloc_device(struct ib_device *device);
+int ib_register_device  (struct ib_device *device);
+int ib_deregister_device(struct ib_device *device);
+
 int ib_query_device(struct ib_device *device,
 		    struct ib_device_attr *device_attr);
 
Index: src/linux-kernel/infiniband/include/ts_ib_provider.h
===================================================================
--- src/linux-kernel/infiniband/include/ts_ib_provider.h	(revision 715)
+++ src/linux-kernel/infiniband/include/ts_ib_provider.h	(working copy)
@@ -26,18 +26,8 @@
 
 #include <ib_verbs.h>
 
-int ib_device_register  (struct ib_device *device);
-int ib_device_deregister(struct ib_device *device);
-
-void ib_completion_event_dispatch(struct ib_cq *cq);
 void ib_async_event_dispatch(struct ib_async_event_record *event_record);
 
-/* Defines to support legacy code -- don't use the tsIb names in new code. */
-#define tsIbDeviceRegister               ib_device_register
-#define tsIbDeviceDeregister             ib_device_deregister
-#define tsIbCompletionEventDispatch      ib_completion_event_dispatch
-#define tsIbAsyncEventDispatch           ib_async_event_dispatch
-
 #endif /* _TS_IB_PROVIDER_H */
 
 /*
Index: src/linux-kernel/infiniband/core/Makefile
===================================================================
--- src/linux-kernel/infiniband/core/Makefile	(revision 715)
+++ src/linux-kernel/infiniband/core/Makefile	(working copy)
@@ -35,6 +35,7 @@
     header_main.o \
     header_ud.o \
     ib_verbs.o \
+    ib_sysfs.o \
     core_main.o \
     core_device.o \
     core_fmr_pool.o \
Index: src/linux-kernel/infiniband/core/core_main.c
===================================================================
--- src/linux-kernel/infiniband/core/core_main.c	(revision 715)
+++ src/linux-kernel/infiniband/core/core_main.c	(working copy)
@@ -21,17 +21,11 @@
   $Id$
 */
 
-#include "core_priv.h"
-
-#include "ts_kernel_trace.h"
-#include "ts_kernel_services.h"
-
-#include <linux/version.h>
 #include <linux/module.h>
-
 #include <linux/init.h>
-#include <linux/errno.h>
 
+#include "core_priv.h"
+
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("core kernel IB API");
 MODULE_LICENSE("Dual BSD/GPL");
@@ -40,30 +34,26 @@
 {
 	int ret;
 
-	TS_REPORT_INIT(MOD_KERNEL_IB,
-		       "Initializing core IB layer");
+	ret = ib_sysfs_setup();
+	if (ret) {
+		printk(KERN_WARNING "Couldn't create InfiniBand device class\n");
+		return ret;
+	}
 
 	ret = ib_create_proc_dir();
 	if (ret) {
-		TS_REPORT_WARN(MOD_KERNEL_IB, "Couldn't create IB core proc directory");
+		ib_sysfs_cleanup();
+		printk(KERN_WARNING "Couldn't create IB core proc directory\n");
 		return ret;
 	}
 
-	TS_REPORT_INIT(MOD_KERNEL_IB,
-		       "core IB layer initialized");
-
 	return 0;
 }
 
 static void __exit ib_core_cleanup(void)
 {
-	TS_REPORT_CLEANUP(MOD_KERNEL_IB,
-			  "Unloading core IB layer");
-
 	ib_remove_proc_dir();
-
-	TS_REPORT_CLEANUP(MOD_KERNEL_IB,
-			  "core IB layer unloaded");
+	ib_sysfs_cleanup();
 }
 
 module_init(ib_core_init);
Index: src/linux-kernel/infiniband/core/core_priv.h
===================================================================
--- src/linux-kernel/infiniband/core/core_priv.h	(revision 715)
+++ src/linux-kernel/infiniband/core/core_priv.h	(working copy)
@@ -80,6 +80,11 @@
 void ib_completion_thread(struct list_head *entry, void *device_ptr);
 void ib_async_thread(struct list_head *entry, void *device_ptr);
 
+int  ib_device_register_sysfs(struct ib_device *device);
+void ib_device_deregister_sysfs(struct ib_device *device);
+int  ib_sysfs_setup(void);
+void ib_sysfs_cleanup(void);
+
 #endif /* _CORE_PRIV_H */
 
 /*
Index: src/linux-kernel/infiniband/core/ib_sysfs.c
===================================================================
--- src/linux-kernel/infiniband/core/ib_sysfs.c	(revision 0)
+++ src/linux-kernel/infiniband/core/ib_sysfs.c	(revision 0)
@@ -0,0 +1,70 @@
+/*
+  This software is available to you under a choice of one of two
+  licenses.  You may choose to be licensed under the terms of the GNU
+  General Public License (GPL) Version 2, available at
+  <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD
+  license, available in the LICENSE.TXT file accompanying this
+  software.  These details are also available at
+  <http://openib.org/license.html>.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+
+  Copyright (c) 2004 Topspin Corporation.  All rights reserved.
+*/
+
+#include "core_priv.h"
+
+static void ib_device_release(struct class_device *cdev)
+{
+	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
+
+	kfree(dev);
+}
+
+static int ib_device_hotplug(struct class_device *dev, char **envp,
+			     int num_envp, char *buffer, int buffer_size)
+{
+	/* What do we want to pass to userspace?  GUID=<guid>? */
+	return 0;
+}
+
+static struct class ib_class = {
+	.name    = "infiniband",
+	.release = ib_device_release,
+	.hotplug = ib_device_hotplug,
+};
+
+int ib_device_register_sysfs(struct ib_device *device)
+{
+	struct class_device *class_dev = &device->class_dev;
+
+	class_dev->class      = &ib_class;
+	class_dev->class_data = device;
+	strlcpy(class_dev->class_id, device->name, BUS_ID_SIZE);
+
+	return class_device_register(class_dev);
+
+
+}
+
+void ib_device_deregister_sysfs(struct ib_device *device)
+{
+	class_device_unregister(&device->class_dev);
+}
+
+int ib_sysfs_setup(void)
+{
+	return class_register(&ib_class);
+}
+
+void ib_sysfs_cleanup(void)
+{
+	class_unregister(&ib_class);
+}

Property changes on: src/linux-kernel/infiniband/core/ib_sysfs.c
___________________________________________________________________
Name: svn:keywords
   + Id

Index: src/linux-kernel/infiniband/core/core_device.c
===================================================================
--- src/linux-kernel/infiniband/core/core_device.c	(revision 715)
+++ src/linux-kernel/infiniband/core/core_device.c	(working copy)
@@ -21,9 +21,6 @@
   $Id$
 */
 
-#include "core_priv.h"
-
-#include "ts_kernel_trace.h"
 #include "ts_kernel_services.h"
 
 #include <linux/string.h>
@@ -33,6 +30,8 @@
 
 #include <asm/semaphore.h>
 
+#include "core_priv.h"
+
 static LIST_HEAD(device_list);
 static LIST_HEAD(notifier_list);
 static DECLARE_MUTEX(device_lock);
@@ -68,9 +67,8 @@
 
 	for (i = 0; i < sizeof mandatory_table / sizeof mandatory_table[0]; ++i) {
 		if (!*(void **) ((void *) device + mandatory_table[i].offset)) {
-			TS_REPORT_WARN(MOD_KERNEL_IB,
-				       "Device %s is missing mandatory function %s",
-				       device->name, mandatory_table[i].name);
+			printk(KERN_WARNING "Device %s is missing mandatory function %s\n",
+			       device->name, mandatory_table[i].name);
 			return -EINVAL;
 		}
 	}
@@ -122,8 +120,38 @@
 	return 0;
 }
 
-int ib_device_register(struct ib_device *device)
+struct ib_device *ib_alloc_device(size_t size)
 {
+	void *dev;
+
+	BUG_ON(size < sizeof (struct ib_device));
+
+	dev = kmalloc(size, GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	memset(dev, 0, size);
+
+	return dev;
+}
+EXPORT_SYMBOL(ib_alloc_device);
+
+void ib_dealloc_device(struct ib_device *device)
+{
+	if (device->reg_state == IB_DEV_UNINITIALIZED) {
+		kfree(device);
+		return;
+	}
+
+	printk(KERN_ERR "device->reg_state = %d\n", device->reg_state);
+	BUG_ON(device->reg_state != IB_DEV_UNREGISTERED);
+
+	ib_device_deregister_sysfs(device);
+}
+EXPORT_SYMBOL(ib_dealloc_device);
+
+int ib_register_device(struct ib_device *device)
+{
 	struct ib_device_private   *priv;
 	struct ib_device_attr       prop;
 	int                         ret;
@@ -143,8 +171,7 @@
 
 	priv = kmalloc(sizeof *priv, GFP_KERNEL);
 	if (!priv) {
-		TS_REPORT_WARN(MOD_KERNEL_IB,
-			       "Couldn't allocate private struct for %s",
+		printk(KERN_WARNING "Couldn't allocate private struct for %s\n",
 			       device->name);
 		ret = -ENOMEM;
 		goto out;
@@ -154,8 +181,7 @@
 
 	ret = device->query_device(device, &prop);
 	if (ret) {
-		TS_REPORT_WARN(MOD_KERNEL_IB,
-			       "query_device failed for %s",
+		printk(KERN_WARNING "query_device failed for %s\n",
 			       device->name);
 		goto out_free;
 	}
@@ -172,8 +198,7 @@
 	priv->port_data = kmalloc((priv->end_port + 1) * sizeof (struct ib_port_data),
 				  GFP_KERNEL);
 	if (!priv->port_data) {
-		TS_REPORT_WARN(MOD_KERNEL_IB,
-			       "Couldn't allocate port info for %s",
+		printk(KERN_WARNING "Couldn't allocate port info for %s\n",
 			       device->name);
 		goto out_free;
 	}
@@ -190,8 +215,7 @@
 
 	ret = ib_cache_setup(device);
 	if (ret) {
-		TS_REPORT_WARN(MOD_KERNEL_IB,
-			       "Couldn't create device info cache for %s",
+		printk(KERN_WARNING "Couldn't create device info cache for %s\n",
 			       device->name);
 		goto out_free_port;
 	}
@@ -201,20 +225,24 @@
 				       device,
 				       &priv->async_thread);
 	if (ret) {
-		TS_REPORT_WARN(MOD_KERNEL_IB,
-			       "Couldn't start async thread for %s",
+		printk(KERN_WARNING "Couldn't start async thread for %s\n",
 			       device->name);
 		goto out_free_cache;
 	}
 
 	ret = ib_proc_setup(device, device->node_type == IB_NODE_SWITCH);
 	if (ret) {
-		TS_REPORT_WARN(MOD_KERNEL_IB,
-			       "Couldn't create /proc dir for %s",
+		printk(KERN_WARNING "Couldn't create /proc dir for %s\n",
 			       device->name);
 		goto out_stop_async;
 	}
 
+	if (ib_device_register_sysfs(device)) {
+		printk(KERN_WARNING "Couldn't register device %s with driver model\n",
+		       device->name);
+		goto out_proc;
+	}
+
 	list_add_tail(&device->core_list, &device_list);
 	{
 		struct list_head          *ptr;
@@ -226,9 +254,14 @@
 		}
 	}
 
+	device->reg_state = IB_DEV_REGISTERED;
+
 	up(&device_lock);
 	return 0;
 
+ out_proc:
+	ib_proc_cleanup(device);
+
  out_stop_async:
 	tsKernelQueueThreadStop(priv->async_thread);
 
@@ -245,17 +278,18 @@
 	up(&device_lock);
 	return ret;
 }
-EXPORT_SYMBOL(ib_device_register);
+EXPORT_SYMBOL(ib_register_device);
 
-int ib_device_deregister(struct ib_device *device)
+int ib_deregister_device(struct ib_device *device)
 {
 	struct ib_device_private *priv;
 
+	printk(KERN_ERR "device->reg_state = %d\n", device->reg_state);
+
 	priv = device->core;
 
 	if (tsKernelQueueThreadStop(priv->async_thread)) {
-		TS_REPORT_WARN(MOD_KERNEL_IB,
-			       "tsKernelThreadStop failed for %s async thread",
+		printk(KERN_WARNING "tsKernelThreadStop failed for %s async thread\n",
 			       device->name);
 	}
 
@@ -278,9 +312,12 @@
 	kfree(priv->port_data);
 	kfree(priv);
 
+	device->reg_state = IB_DEV_UNREGISTERED;
+	printk(KERN_ERR "device->reg_state = %d\n", device->reg_state);
+
 	return 0;
 }
-EXPORT_SYMBOL(ib_device_deregister);
+EXPORT_SYMBOL(ib_deregister_device);
 
 struct ib_device *ib_device_get_by_name(const char *name)
 {
Index: src/linux-kernel/infiniband/hw/mthca/mthca_dev.h
===================================================================
--- src/linux-kernel/infiniband/hw/mthca/mthca_dev.h	(revision 715)
+++ src/linux-kernel/infiniband/hw/mthca/mthca_dev.h	(working copy)
@@ -178,7 +178,8 @@
 };
 
 struct mthca_dev {
-	struct pci_dev  *pdev;
+	struct ib_device  ib_dev;
+	struct pci_dev   *pdev;
 
 	int          	 hca_type;
 	unsigned long	 mthca_flags;
@@ -209,8 +210,6 @@
 
 	struct mthca_pd       driver_pd;
 	struct mthca_mr       driver_mr;
-
-	struct ib_device      ib_dev;
 };
 
 #define mthca_printk(level, mdev, format, arg...) \
Index: src/linux-kernel/infiniband/hw/mthca/mthca_main.c
===================================================================
--- src/linux-kernel/infiniband/hw/mthca/mthca_main.c	(revision 715)
+++ src/linux-kernel/infiniband/hw/mthca/mthca_main.c	(working copy)
@@ -495,14 +495,13 @@
 		}
 	}
 
-	mdev = kmalloc(sizeof *mdev, GFP_KERNEL);
+	mdev = (struct mthca_dev *) ib_alloc_device(sizeof *mdev);
 	if (!mdev) {
 		dev_err(&pdev->dev, "Device struct alloc failed, "
 			"aborting.\n");
 		err = -ENOMEM;
 		goto err_out_free_res;
 	}
-	memset(mdev, 0, sizeof *mdev);
 
 	mdev->pdev     = pdev;
 	mdev->hca_type = id->driver_data;
@@ -617,7 +616,7 @@
 	if (mdev->mthca_flags & MTHCA_FLAG_MSI)
 		pci_disable_msi(pdev);
 
-	kfree(mdev);
+	ib_dealloc_device((struct ib_device *) mdev);
 
 err_out_free_res:
 	mthca_release_regions(pdev, ddr_hidden);
@@ -663,7 +662,7 @@
 		if (mdev->mthca_flags & MTHCA_FLAG_MSI)
 			pci_disable_msi(pdev);
 
-		kfree(mdev);
+		ib_dealloc_device((struct ib_device *) mdev);
 		mthca_release_regions(pdev, mdev->mthca_flags &
 				      MTHCA_FLAG_DDR_HIDDEN);
 		pci_disable_device(pdev);
Index: src/linux-kernel/infiniband/hw/mthca/mthca_provider.c
===================================================================
--- src/linux-kernel/infiniband/hw/mthca/mthca_provider.c	(revision 715)
+++ src/linux-kernel/infiniband/hw/mthca/mthca_provider.c	(working copy)
@@ -545,12 +545,12 @@
 	dev->ib_dev.detach_mcast         = mthca_multicast_detach;
 	dev->ib_dev.mad_process          = mthca_process_mad;
 
-	return ib_device_register(&dev->ib_dev);
+	return ib_register_device(&dev->ib_dev);
 }
 
 void mthca_deregister_device(struct mthca_dev *dev)
 {
-	ib_device_deregister(&dev->ib_dev);
+	ib_deregister_device(&dev->ib_dev);
 }
 
 /*




More information about the general mailing list