[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