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>
This commit is contained in:
Ralph Campbell 2010-05-06 17:03:25 -07:00 committed by Roland Dreier
parent a0fe3cc5d3
commit 9a6edb60ec
12 changed files with 35 additions and 16 deletions

View file

@ -38,7 +38,9 @@
#include <rdma/ib_verbs.h> #include <rdma/ib_verbs.h>
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 *));
void ib_device_unregister_sysfs(struct ib_device *device); void ib_device_unregister_sysfs(struct ib_device *device);
int ib_sysfs_setup(void); int ib_sysfs_setup(void);

View file

@ -267,7 +267,9 @@ out:
* callback for each device that is added. @device must be allocated * callback for each device that is added. @device must be allocated
* with ib_alloc_device(). * with ib_alloc_device().
*/ */
int ib_register_device(struct ib_device *device) int ib_register_device(struct ib_device *device,
int (*port_callback)(struct ib_device *,
u8, struct kobject *))
{ {
int ret; int ret;
@ -296,7 +298,7 @@ int ib_register_device(struct ib_device *device)
goto out; goto out;
} }
ret = ib_device_register_sysfs(device); ret = ib_device_register_sysfs(device, port_callback);
if (ret) { if (ret) {
printk(KERN_WARNING "Couldn't register device %s with driver model\n", printk(KERN_WARNING "Couldn't register device %s with driver model\n",
device->name); device->name);

View file

@ -475,7 +475,9 @@ err:
return NULL; 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 *p;
struct ib_port_attr attr; struct ib_port_attr attr;
@ -522,11 +524,20 @@ static int add_port(struct ib_device *device, int port_num)
if (ret) if (ret)
goto err_free_pkey; 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); list_add_tail(&p->kobj.entry, &device->port_list);
kobject_uevent(&p->kobj, KOBJ_ADD); kobject_uevent(&p->kobj, KOBJ_ADD);
return 0; return 0;
err_remove_pkey:
sysfs_remove_group(&p->kobj, &p->pkey_group);
err_free_pkey: err_free_pkey:
for (i = 0; i < attr.pkey_tbl_len; ++i) for (i = 0; i < attr.pkey_tbl_len; ++i)
kfree(p->pkey_group.attrs[i]); kfree(p->pkey_group.attrs[i]);
@ -754,7 +765,9 @@ static struct attribute_group iw_stats_group = {
.attrs = iw_proto_stats_attrs, .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; struct device *class_dev = &device->dev;
int ret; int ret;
@ -785,12 +798,12 @@ int ib_device_register_sysfs(struct ib_device *device)
} }
if (device->node_type == RDMA_NODE_IB_SWITCH) { if (device->node_type == RDMA_NODE_IB_SWITCH) {
ret = add_port(device, 0); ret = add_port(device, 0, port_callback);
if (ret) if (ret)
goto err_put; goto err_put;
} else { } else {
for (i = 1; i <= device->phys_port_cnt; ++i) { for (i = 1; i <= device->phys_port_cnt; ++i) {
ret = add_port(device, i); ret = add_port(device, i, port_callback);
if (ret) if (ret)
goto err_put; goto err_put;
} }

View file

@ -865,7 +865,7 @@ int c2_register_device(struct c2_dev *dev)
dev->ibdev.iwcm->create_listen = c2_service_create; dev->ibdev.iwcm->create_listen = c2_service_create;
dev->ibdev.iwcm->destroy_listen = c2_service_destroy; dev->ibdev.iwcm->destroy_listen = c2_service_destroy;
ret = ib_register_device(&dev->ibdev); ret = ib_register_device(&dev->ibdev, NULL);
if (ret) if (ret)
goto out_free_iwcm; goto out_free_iwcm;

View file

@ -1428,7 +1428,7 @@ int iwch_register_device(struct iwch_dev *dev)
dev->ibdev.iwcm->rem_ref = iwch_qp_rem_ref; dev->ibdev.iwcm->rem_ref = iwch_qp_rem_ref;
dev->ibdev.iwcm->get_qp = iwch_get_qp; dev->ibdev.iwcm->get_qp = iwch_get_qp;
ret = ib_register_device(&dev->ibdev); ret = ib_register_device(&dev->ibdev, NULL);
if (ret) if (ret)
goto bail1; goto bail1;

View file

@ -486,7 +486,7 @@ int c4iw_register_device(struct c4iw_dev *dev)
dev->ibdev.iwcm->rem_ref = c4iw_qp_rem_ref; dev->ibdev.iwcm->rem_ref = c4iw_qp_rem_ref;
dev->ibdev.iwcm->get_qp = c4iw_get_qp; dev->ibdev.iwcm->get_qp = c4iw_get_qp;
ret = ib_register_device(&dev->ibdev); ret = ib_register_device(&dev->ibdev, NULL);
if (ret) if (ret)
goto bail1; goto bail1;

View file

@ -798,7 +798,7 @@ static int __devinit ehca_probe(struct of_device *dev,
goto probe5; goto probe5;
} }
ret = ib_register_device(&shca->ib_device); ret = ib_register_device(&shca->ib_device, NULL);
if (ret) { if (ret) {
ehca_err(&shca->ib_device, ehca_err(&shca->ib_device,
"ib_register_device() failed ret=%i", ret); "ib_register_device() failed ret=%i", ret);

View file

@ -2182,7 +2182,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
snprintf(dev->node_desc, sizeof(dev->node_desc), snprintf(dev->node_desc, sizeof(dev->node_desc),
IPATH_IDSTR " %s", init_utsname()->nodename); IPATH_IDSTR " %s", init_utsname()->nodename);
ret = ib_register_device(dev); ret = ib_register_device(dev, NULL);
if (ret) if (ret)
goto err_reg; goto err_reg;

View file

@ -662,7 +662,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
spin_lock_init(&ibdev->sm_lock); spin_lock_init(&ibdev->sm_lock);
mutex_init(&ibdev->cap_mask_mutex); mutex_init(&ibdev->cap_mask_mutex);
if (ib_register_device(&ibdev->ib_dev)) if (ib_register_device(&ibdev->ib_dev, NULL))
goto err_map; goto err_map;
if (mlx4_ib_mad_init(ibdev)) if (mlx4_ib_mad_init(ibdev))

View file

@ -1403,7 +1403,7 @@ int mthca_register_device(struct mthca_dev *dev)
mutex_init(&dev->cap_mask_mutex); mutex_init(&dev->cap_mask_mutex);
ret = ib_register_device(&dev->ib_dev); ret = ib_register_device(&dev->ib_dev, NULL);
if (ret) if (ret)
return ret; return ret;

View file

@ -3962,7 +3962,7 @@ int nes_register_ofa_device(struct nes_ib_device *nesibdev)
struct nes_adapter *nesadapter = nesdev->nesadapter; struct nes_adapter *nesadapter = nesdev->nesadapter;
int i, ret; int i, ret;
ret = ib_register_device(&nesvnic->nesibdev->ibdev); ret = ib_register_device(&nesvnic->nesibdev->ibdev, NULL);
if (ret) { if (ret) {
return ret; return ret;
} }

View file

@ -1172,7 +1172,9 @@ struct ib_client {
struct ib_device *ib_alloc_device(size_t size); struct ib_device *ib_alloc_device(size_t size);
void ib_dealloc_device(struct ib_device *device); void ib_dealloc_device(struct ib_device *device);
int ib_register_device (struct ib_device *device); int ib_register_device(struct ib_device *device,
int (*port_callback)(struct ib_device *,
u8, struct kobject *));
void ib_unregister_device(struct ib_device *device); void ib_unregister_device(struct ib_device *device);
int ib_register_client (struct ib_client *client); int ib_register_client (struct ib_client *client);