aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/sysfs.c
diff options
context:
space:
mode:
authorRalph Campbell <ralph.campbell@qlogic.com>2010-05-06 17:03:25 -0700
committerRoland Dreier <rolandd@cisco.com>2010-05-21 10:34:44 -0700
commit9a6edb60ec10d86b1025a0cdad68fd89f1ddaf02 (patch)
tree8727118d511e8336f038e618cfc6d4aa6b73aaaf /drivers/infiniband/core/sysfs.c
parentMerge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input (diff)
downloadlinux-dev-9a6edb60ec10d86b1025a0cdad68fd89f1ddaf02.tar.xz
linux-dev-9a6edb60ec10d86b1025a0cdad68fd89f1ddaf02.zip
IB/core: Allow device-specific per-port sysfs files
Add a new parameter to ib_register_device() so that low-level device drivers can pass in a pointer to a callback function that will be called for each port that is registered in sysfs. This allows low-level device drivers to create files in /sys/class/infiniband/<hca>/ports/<N>/ without having to poke through the internals of the RDMA sysfs handling. There is no need for an unregister function since the kobject reference will go to zero when ib_unregister_device() is called. Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/core/sysfs.c')
-rw-r--r--drivers/infiniband/core/sysfs.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index f901957abc8b..3627300e2a10 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -475,7 +475,9 @@ err:
return NULL;
}
-static int add_port(struct ib_device *device, int port_num)
+static int add_port(struct ib_device *device, int port_num,
+ int (*port_callback)(struct ib_device *,
+ u8, struct kobject *))
{
struct ib_port *p;
struct ib_port_attr attr;
@@ -522,11 +524,20 @@ static int add_port(struct ib_device *device, int port_num)
if (ret)
goto err_free_pkey;
+ if (port_callback) {
+ ret = port_callback(device, port_num, &p->kobj);
+ if (ret)
+ goto err_remove_pkey;
+ }
+
list_add_tail(&p->kobj.entry, &device->port_list);
kobject_uevent(&p->kobj, KOBJ_ADD);
return 0;
+err_remove_pkey:
+ sysfs_remove_group(&p->kobj, &p->pkey_group);
+
err_free_pkey:
for (i = 0; i < attr.pkey_tbl_len; ++i)
kfree(p->pkey_group.attrs[i]);
@@ -754,7 +765,9 @@ static struct attribute_group iw_stats_group = {
.attrs = iw_proto_stats_attrs,
};
-int ib_device_register_sysfs(struct ib_device *device)
+int ib_device_register_sysfs(struct ib_device *device,
+ int (*port_callback)(struct ib_device *,
+ u8, struct kobject *))
{
struct device *class_dev = &device->dev;
int ret;
@@ -785,12 +798,12 @@ int ib_device_register_sysfs(struct ib_device *device)
}
if (device->node_type == RDMA_NODE_IB_SWITCH) {
- ret = add_port(device, 0);
+ ret = add_port(device, 0, port_callback);
if (ret)
goto err_put;
} else {
for (i = 1; i <= device->phys_port_cnt; ++i) {
- ret = add_port(device, i);
+ ret = add_port(device, i, port_callback);
if (ret)
goto err_put;
}