[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