[openfabrics-ewg] [PATCH 2 of 2 IB/VNIC] Add VNIC backport patch files for RHEL 4 Update 3

Ramachandra K ramachandra.kuchimanchi at qlogic.com
Tue Jan 9 03:45:59 PST 2007


Adds two VNIC backport patch files to support VNIC on RHEL4 Update 3

vnic_sysfs_nested_class_dev.patch - Adds support to VNIC driver to create
nested class device structure in sysfs for older kernels

vnic_utsname.patch - Uses old system_utsname for older kernels

Signed-off-by: Ramachandra K <ramachandra.kuchimanchi at qlogic.com>
---

 .../2.6.9_U3/vnic_sysfs_nested_class_dev.patch     |  281 +++++++++++++++++++++++
 .../backport/2.6.9_U3/vnic_utsname.patch           |   50 ++++
 2 files changed, 331 insertions(+), 0 deletions(-)

diff --git a/kernel_patches/backport/2.6.9_U3/vnic_sysfs_nested_class_dev.patch 
b/kernel_patches/backport/2.6.9_U3/vnic_sysfs_nested_class_dev.patch
new file mode 100644
index 0000000..88cfdd1
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U3/vnic_sysfs_nested_class_dev.patch
@@ -0,0 +1,281 @@
+This patch adds support to the VNIC driver to create a nested class_device
+structure in sysfs for older kernels.(The ability to create nested
+class_device structure in sysfs was added in 2.6.14)
+
+Signed-off-by: Ramachandra K <ramachandra.kuchimanchi at qlogic.com>
+---
+
+ drivers/infiniband/ulp/vnic/vnic_main.c    |    3 -
+ drivers/infiniband/ulp/vnic/vnic_netpath.c |    3 -
+ drivers/infiniband/ulp/vnic/vnic_stats.h   |   10 +-
+ drivers/infiniband/ulp/vnic/vnic_sys.c     |  138 +++++++++++++++++++++++++++-
+ drivers/infiniband/ulp/vnic/vnic_sys.h     |   10 ++
+ 5 files changed, 151 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/infiniband/ulp/vnic/vnic_main.c b/drivers/infiniband/ulp/vnic/vnic_main.c
+index 5810bc8..9407f9d 100644
+--- a/drivers/infiniband/ulp/vnic/vnic_main.c
++++ b/drivers/infiniband/ulp/vnic/vnic_main.c
+@@ -681,7 +681,8 @@ static void vnic_handle_free_vnic_evt(st
+	sysfs_remove_group(&vnic->class_dev_info.class_dev.kobj,
+			   &vnic_dev_attr_group);
+	vnic_cleanup_stats_files(vnic);
+-	class_device_unregister(&vnic->class_dev_info.class_dev);
++	vnic_nested_class_device_unregister(&vnic->class_dev_info.class_dev,
++					    &interface_cdev.class_dev);
+	wait_for_completion(&vnic->class_dev_info.released);
+ }
+
+diff --git a/drivers/infiniband/ulp/vnic/vnic_netpath.c b/drivers/infiniband/ulp/vnic/vnic_netpath.c
+index ce54608..29217e9 100644
+--- a/drivers/infiniband/ulp/vnic/vnic_netpath.c
++++ b/drivers/infiniband/ulp/vnic/vnic_netpath.c
+@@ -84,7 +84,8 @@ void netpath_free(struct netpath *netpat
+	netpath->viport = NULL;
+	sysfs_remove_group(&netpath->class_dev_info.class_dev.kobj,
+			   &vnic_path_attr_group);
+-	class_device_unregister(&netpath->class_dev_info.class_dev);
++	vnic_nested_class_device_unregister(&netpath->class_dev_info.class_dev,
++				    &netpath->parent->class_dev_info.class_dev);
+	wait_for_completion(&netpath->class_dev_info.released);
+ }
+
+diff --git a/drivers/infiniband/ulp/vnic/vnic_stats.h b/drivers/infiniband/ulp/vnic/vnic_stats.h
+index 7d1b953..cda43a5 100644
+--- a/drivers/infiniband/ulp/vnic/vnic_stats.h
++++ b/drivers/infiniband/ulp/vnic/vnic_stats.h
+@@ -111,11 +111,11 @@ static inline int vnic_setup_stats_files
+ {
+	init_completion(&vnic->stat_info.released);
+	vnic->stat_info.class_dev.class = &vnic_class;
+-	vnic->stat_info.class_dev.parent = &vnic->class_dev_info.class_dev;
+	snprintf(vnic->stat_info.class_dev.class_id, BUS_ID_SIZE,
+		 "stats");
+
+-	if (class_device_register(&vnic->stat_info.class_dev)) {
++	if (vnic_nested_class_device_register(&vnic->stat_info.class_dev,
++				      &vnic->class_dev_info.class_dev)) {
+		SYS_ERROR("create_vnic: error in registering"
+			  " stat class dev\n");
+		goto stats_out;
+@@ -127,7 +127,8 @@ static inline int vnic_setup_stats_files
+
+	return 0;
+ err_stats_file:
+-	class_device_unregister(&vnic->stat_info.class_dev);
++	vnic_nested_class_device_unregister(&vnic->stat_info.class_dev,
++					    &vnic->class_dev_info.class_dev);
+	wait_for_completion(&vnic->stat_info.released);
+ stats_out:
+	return -1;
+@@ -137,7 +138,8 @@ static inline void vnic_cleanup_stats_fi
+ {
+	sysfs_remove_group(&vnic->class_dev_info.class_dev.kobj,
+			   &vnic_stats_attr_group);
+-	class_device_unregister(&vnic->stat_info.class_dev);
++	vnic_nested_class_device_unregister(&vnic->stat_info.class_dev,
++					    &vnic->class_dev_info.class_dev);
+	wait_for_completion(&vnic->stat_info.released);
+ }
+
+diff --git a/drivers/infiniband/ulp/vnic/vnic_sys.c b/drivers/infiniband/ulp/vnic/vnic_sys.c
+index 034be7c..b07c5d0 100644
+--- a/drivers/infiniband/ulp/vnic/vnic_sys.c
++++ b/drivers/infiniband/ulp/vnic/vnic_sys.c
+@@ -440,11 +440,11 @@ struct vnic *create_vnic(struct path_par
+	init_completion(&vnic->class_dev_info.released);
+
+	vnic->class_dev_info.class_dev.class = &vnic_class;
+-	vnic->class_dev_info.class_dev.parent = &interface_cdev.class_dev;
+	snprintf(vnic->class_dev_info.class_dev.class_id, BUS_ID_SIZE,
+		 vnic_config->name);
+
+-	if (class_device_register(&vnic->class_dev_info.class_dev)) {
++	if (vnic_nested_class_device_register(&vnic->class_dev_info.class_dev,
++					      &interface_cdev.class_dev)) {
+		SYS_ERROR("create_vnic: error in registering"
+			  " vnic class dev\n");
+		goto free_vnic;
+@@ -466,7 +466,8 @@ err_stats:
+	sysfs_remove_group(&vnic->class_dev_info.class_dev.kobj,
+			   &vnic_dev_attr_group);
+ err_attr:
+-	class_device_unregister(&vnic->class_dev_info.class_dev);
++	vnic_nested_class_device_unregister(&vnic->class_dev_info.class_dev,
++					    &interface_cdev.class_dev);
+	wait_for_completion(&vnic->class_dev_info.released);
+ free_vnic:
+	list_del(&vnic->list_ptrs);
+@@ -642,12 +643,11 @@ static int setup_path_class_files(struct
+	init_completion(&path->class_dev_info.released);
+
+	path->class_dev_info.class_dev.class = &vnic_class;
+-	path->class_dev_info.class_dev.parent =
+-	    &path->parent->class_dev_info.class_dev;
+	snprintf(path->class_dev_info.class_dev.class_id,
+		 BUS_ID_SIZE, name);
+
+-	if (class_device_register(&path->class_dev_info.class_dev)) {
++	if (vnic_nested_class_device_register(&path->class_dev_info.class_dev,
++				&path->parent->class_dev_info.class_dev)) {
+		SYS_ERROR("error in registering path class dev\n");
+		goto out;
+	}
+@@ -661,7 +661,8 @@ static int setup_path_class_files(struct
+	return 0;
+
+ err_path:
+-	class_device_unregister(&path->class_dev_info.class_dev);
++	vnic_nested_class_device_unregister(&path->class_dev_info.class_dev,
++				     &path->parent->class_dev_info.class_dev);
+	wait_for_completion(&path->class_dev_info.released);
+ out:
+	return -1;
+@@ -784,3 +785,126 @@ free_vnic:
+ out:
+	return ret;
+ }
++
++/*
++ * The ability to nest class_device structures was added in 2.6.14.
++ * Following functions are for providing similar functionality
++ * for older kernels
++ */
++
++static int class_device_dev_link(struct class_device * class_dev)
++{
++	if (class_dev->dev)
++		return sysfs_create_link(&class_dev->kobj,
++					 &class_dev->dev->kobj, "device");
++	return 0;
++}
++
++static int class_device_driver_link(struct class_device * class_dev)
++{
++	if ((class_dev->dev) && (class_dev->dev->driver))
++		return sysfs_create_link(&class_dev->kobj,
++				 &class_dev->dev->driver->kobj, "driver");
++	return 0;
++}
++
++static int class_device_add_attrs(struct class_device * cd)
++{
++	int i;
++	int error = 0;
++	struct class * cls = cd->class;
++
++	if (cls->class_dev_attrs) {
++		for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) {
++			error = class_device_create_file(cd,
++						 &cls->class_dev_attrs[i]);
++			if (error)
++				goto Err;
++		}
++	}
++ Done:
++	return error;
++ Err:
++	while (--i >= 0)
++		class_device_remove_file(cd,&cls->class_dev_attrs[i]);
++	goto Done;
++}
++
++static int vnic_nested_class_device_add(struct class_device *class_dev,
++					struct class_device *parent_dev)
++{
++	struct class * parent = NULL;
++	struct class_interface * class_intf;
++	int error;
++
++	class_dev = class_device_get(class_dev);
++	if (!class_dev)
++		return -EINVAL;
++
++	if (!strlen(class_dev->class_id)) {
++		error = -EINVAL;
++		goto register_done;
++	}
++
++	parent = class_get(class_dev->class);
++
++	pr_debug("CLASS: registering class device: ID = '%s'\n",
++		 class_dev->class_id);
++
++	/* first, register with generic layer. */
++	kobject_set_name(&class_dev->kobj, class_dev->class_id);
++
++	class_dev->kobj.parent = &parent_dev->kobj;
++
++	if ((error = kobject_add(&class_dev->kobj)))
++		goto register_done;
++
++	/* now take care of our own registration */
++	if (parent) {
++		down_write(&parent->subsys.rwsem);
++		list_add_tail(&class_dev->node, &parent->children);
++		list_for_each_entry(class_intf, &parent->interfaces, node)
++			if (class_intf->add)
++				class_intf->add(class_dev);
++		up_write(&parent->subsys.rwsem);
++	}
++	class_device_add_attrs(class_dev);
++	class_device_dev_link(class_dev);
++	class_device_driver_link(class_dev);
++
++ register_done:
++	if (error && parent)
++		class_put(parent);
++	class_device_put(class_dev);
++	return error;
++}
++
++/*
++ * vnic_nested_class_device_register()
++ * Similar to class_device_register() but sets the parent
++ * of the class_device to the specified class_device.
++ *
++ */
++int vnic_nested_class_device_register(struct class_device *class_dev,
++				      struct class_device *parent_dev)
++{
++	int ret;
++	parent_dev = class_device_get(parent_dev);
++
++	if (!parent_dev)
++		return -EINVAL;
++
++	class_device_initialize(class_dev);
++
++	if((ret = vnic_nested_class_device_add(class_dev, parent_dev)))
++		class_device_put(parent_dev);
++
++	return ret;
++}
++
++void vnic_nested_class_device_unregister(struct class_device *class_dev,
++					 struct class_device *parent_dev)
++{
++	class_device_unregister(class_dev);
++	class_device_put(parent_dev);
++}
+diff --git a/drivers/infiniband/ulp/vnic/vnic_sys.h b/drivers/infiniband/ulp/vnic/vnic_sys.h
+index 5835c4a..d15d18a 100644
+--- a/drivers/infiniband/ulp/vnic/vnic_sys.h
++++ b/drivers/infiniband/ulp/vnic/vnic_sys.h
+@@ -38,6 +38,16 @@ struct class_dev_info {
+	struct completion	released;
+ };
+
++/*
++ * vnic_nested_class_device_register()
++ * Similar to class_device_register() but sets the parent
++ * of the class_device to the specified class_device.
++ *
++ */
++int vnic_nested_class_device_register(struct class_device *class_dev,
++				      struct class_device *parent_dev);
++void vnic_nested_class_device_unregister(struct class_device *class_dev,
++					 struct class_device *parent_dev);
+ extern struct class vnic_class;
+ extern struct class_dev_info interface_cdev;
+ extern struct attribute_group vnic_dev_attr_group;
diff --git a/kernel_patches/backport/2.6.9_U3/vnic_utsname.patch 
b/kernel_patches/backport/2.6.9_U3/vnic_utsname.patch
new file mode 100644
index 0000000..dfd98d9
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U3/vnic_utsname.patch
@@ -0,0 +1,50 @@
+Use the old system_utsname instead of init_utsname() for older kernels.
+Also explicit inclusion of linux/types.h required to avoid compilation error
+from linux/parser.h (seen on 2.6.16).
+
+Signed-off-by: Ramachandra K <ramachandra.kuchimanchi at qlogic.com>
+---
+
+ drivers/infiniband/ulp/vnic/vnic_config.c |    8 ++++----
+ drivers/infiniband/ulp/vnic/vnic_sys.c    |    1 +
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/infiniband/ulp/vnic/vnic_config.c b/drivers/infiniband/ulp/vnic/vnic_config.c
+index d3b02d4..f482e82 100644
+--- a/drivers/infiniband/ulp/vnic/vnic_config.c
++++ b/drivers/infiniband/ulp/vnic/vnic_config.c
+@@ -105,18 +105,18 @@ static void config_control_defaults(stru
+	control_config->ib_config.conn_data.path_id = 0;
+	control_config->ib_config.conn_data.vnic_instance = params->instance;
+	control_config->ib_config.conn_data.path_num = 0;
+-	dot = strchr(init_utsname()->nodename, '.');
++	dot = strchr(system_utsname.nodename, '.');
+
+	if (dot)
+-		len = dot - init_utsname()->nodename;
++		len = dot - system_utsname.nodename;
+	else
+-		len = strlen(init_utsname()->nodename);
++		len = strlen(system_utsname.nodename);
+
+	if (len > VNIC_MAX_NODENAME_LEN)
+		len = VNIC_MAX_NODENAME_LEN;
+
+	memcpy(control_config->ib_config.conn_data.nodename,
+-	       init_utsname()->nodename, len);
++	       system_utsname.nodename, len);
+
+	control_config->ib_config.retry_count = RETRY_COUNT;
+	control_config->ib_config.rnr_retry_count = RETRY_COUNT;
+diff --git a/drivers/infiniband/ulp/vnic/vnic_sys.c b/drivers/infiniband/ulp/vnic/vnic_sys.c
+index 034be7c..0be8517 100644
+--- a/drivers/infiniband/ulp/vnic/vnic_sys.c
++++ b/drivers/infiniband/ulp/vnic/vnic_sys.c
+@@ -30,6 +30,7 @@
+  * SOFTWARE.
+  */
+
++#include <linux/types.h>
+ #include <linux/parser.h>
+ #include <linux/netdevice.h>
+ #include <linux/if.h>






More information about the ewg mailing list