IB/core: Add gid attributes to sysfs

This patch set adds attributes of net device and gid type to each GID
in the GID table. Users that use verbs directly need to specify
the GID index. Since the same GID could have different types or
associated net devices, users should have the ability to query the
associated GID attributes. Adding these attributes to sysfs.

Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
Matan Barak 2015-12-23 14:56:49 +02:00 committed by Doug Ledford
parent cb57bb849e
commit 470be516a2
2 changed files with 198 additions and 2 deletions

View File

@ -0,0 +1,16 @@
What: /sys/class/infiniband/<hca>/ports/<port-number>/gid_attrs/ndevs/<gid-index>
Date: November 29, 2015
KernelVersion: 4.4.0
Contact: linux-rdma@vger.kernel.org
Description: The net-device's name associated with the GID resides
at index <gid-index>.
What: /sys/class/infiniband/<hca>/ports/<port-number>/gid_attrs/types/<gid-index>
Date: November 29, 2015
KernelVersion: 4.4.0
Contact: linux-rdma@vger.kernel.org
Description: The RoCE type of the associated GID resides at index <gid-index>.
This could either be "IB/RoCE v1" for IB and RoCE v1 based GODs
or "RoCE v2" for RoCE v2 based GIDs.

View File

@ -37,12 +37,22 @@
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/netdevice.h>
#include <rdma/ib_mad.h>
struct ib_port;
struct gid_attr_group {
struct ib_port *port;
struct kobject kobj;
struct attribute_group ndev;
struct attribute_group type;
};
struct ib_port {
struct kobject kobj;
struct ib_device *ibdev;
struct gid_attr_group *gid_attr_group;
struct attribute_group gid_group;
struct attribute_group pkey_group;
u8 port_num;
@ -84,6 +94,24 @@ static const struct sysfs_ops port_sysfs_ops = {
.show = port_attr_show
};
static ssize_t gid_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf)
{
struct port_attribute *port_attr =
container_of(attr, struct port_attribute, attr);
struct ib_port *p = container_of(kobj, struct gid_attr_group,
kobj)->port;
if (!port_attr->show)
return -EIO;
return port_attr->show(p, port_attr, buf);
}
static const struct sysfs_ops gid_attr_sysfs_ops = {
.show = gid_attr_show
};
static ssize_t state_show(struct ib_port *p, struct port_attribute *unused,
char *buf)
{
@ -281,6 +309,46 @@ static struct attribute *port_default_attrs[] = {
NULL
};
static size_t print_ndev(struct ib_gid_attr *gid_attr, char *buf)
{
if (!gid_attr->ndev)
return -EINVAL;
return sprintf(buf, "%s\n", gid_attr->ndev->name);
}
static size_t print_gid_type(struct ib_gid_attr *gid_attr, char *buf)
{
return sprintf(buf, "%s\n", ib_cache_gid_type_str(gid_attr->gid_type));
}
static ssize_t _show_port_gid_attr(struct ib_port *p,
struct port_attribute *attr,
char *buf,
size_t (*print)(struct ib_gid_attr *gid_attr,
char *buf))
{
struct port_table_attribute *tab_attr =
container_of(attr, struct port_table_attribute, attr);
union ib_gid gid;
struct ib_gid_attr gid_attr = {};
ssize_t ret;
va_list args;
ret = ib_query_gid(p->ibdev, p->port_num, tab_attr->index, &gid,
&gid_attr);
if (ret)
goto err;
ret = print(&gid_attr, buf);
err:
if (gid_attr.ndev)
dev_put(gid_attr.ndev);
va_end(args);
return ret;
}
static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
char *buf)
{
@ -296,6 +364,19 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
return sprintf(buf, "%pI6\n", gid.raw);
}
static ssize_t show_port_gid_attr_ndev(struct ib_port *p,
struct port_attribute *attr, char *buf)
{
return _show_port_gid_attr(p, attr, buf, print_ndev);
}
static ssize_t show_port_gid_attr_gid_type(struct ib_port *p,
struct port_attribute *attr,
char *buf)
{
return _show_port_gid_attr(p, attr, buf, print_gid_type);
}
static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr,
char *buf)
{
@ -451,12 +532,41 @@ static void ib_port_release(struct kobject *kobj)
kfree(p);
}
static void ib_port_gid_attr_release(struct kobject *kobj)
{
struct gid_attr_group *g = container_of(kobj, struct gid_attr_group,
kobj);
struct attribute *a;
int i;
if (g->ndev.attrs) {
for (i = 0; (a = g->ndev.attrs[i]); ++i)
kfree(a);
kfree(g->ndev.attrs);
}
if (g->type.attrs) {
for (i = 0; (a = g->type.attrs[i]); ++i)
kfree(a);
kfree(g->type.attrs);
}
kfree(g);
}
static struct kobj_type port_type = {
.release = ib_port_release,
.sysfs_ops = &port_sysfs_ops,
.default_attrs = port_default_attrs
};
static struct kobj_type gid_attr_type = {
.sysfs_ops = &gid_attr_sysfs_ops,
.release = ib_port_gid_attr_release
};
static struct attribute **
alloc_group_attrs(ssize_t (*show)(struct ib_port *,
struct port_attribute *, char *buf),
@ -528,9 +638,23 @@ static int add_port(struct ib_device *device, int port_num,
return ret;
}
p->gid_attr_group = kzalloc(sizeof(*p->gid_attr_group), GFP_KERNEL);
if (!p->gid_attr_group) {
ret = -ENOMEM;
goto err_put;
}
p->gid_attr_group->port = p;
ret = kobject_init_and_add(&p->gid_attr_group->kobj, &gid_attr_type,
&p->kobj, "gid_attrs");
if (ret) {
kfree(p->gid_attr_group);
goto err_put;
}
ret = sysfs_create_group(&p->kobj, &pma_group);
if (ret)
goto err_put;
goto err_put_gid_attrs;
p->gid_group.name = "gids";
p->gid_group.attrs = alloc_group_attrs(show_port_gid, attr.gid_tbl_len);
@ -543,12 +667,38 @@ static int add_port(struct ib_device *device, int port_num,
if (ret)
goto err_free_gid;
p->gid_attr_group->ndev.name = "ndevs";
p->gid_attr_group->ndev.attrs = alloc_group_attrs(show_port_gid_attr_ndev,
attr.gid_tbl_len);
if (!p->gid_attr_group->ndev.attrs) {
ret = -ENOMEM;
goto err_remove_gid;
}
ret = sysfs_create_group(&p->gid_attr_group->kobj,
&p->gid_attr_group->ndev);
if (ret)
goto err_free_gid_ndev;
p->gid_attr_group->type.name = "types";
p->gid_attr_group->type.attrs = alloc_group_attrs(show_port_gid_attr_gid_type,
attr.gid_tbl_len);
if (!p->gid_attr_group->type.attrs) {
ret = -ENOMEM;
goto err_remove_gid_ndev;
}
ret = sysfs_create_group(&p->gid_attr_group->kobj,
&p->gid_attr_group->type);
if (ret)
goto err_free_gid_type;
p->pkey_group.name = "pkeys";
p->pkey_group.attrs = alloc_group_attrs(show_port_pkey,
attr.pkey_tbl_len);
if (!p->pkey_group.attrs) {
ret = -ENOMEM;
goto err_remove_gid;
goto err_remove_gid_type;
}
ret = sysfs_create_group(&p->kobj, &p->pkey_group);
@ -576,6 +726,28 @@ err_free_pkey:
kfree(p->pkey_group.attrs);
p->pkey_group.attrs = NULL;
err_remove_gid_type:
sysfs_remove_group(&p->gid_attr_group->kobj,
&p->gid_attr_group->type);
err_free_gid_type:
for (i = 0; i < attr.gid_tbl_len; ++i)
kfree(p->gid_attr_group->type.attrs[i]);
kfree(p->gid_attr_group->type.attrs);
p->gid_attr_group->type.attrs = NULL;
err_remove_gid_ndev:
sysfs_remove_group(&p->gid_attr_group->kobj,
&p->gid_attr_group->ndev);
err_free_gid_ndev:
for (i = 0; i < attr.gid_tbl_len; ++i)
kfree(p->gid_attr_group->ndev.attrs[i]);
kfree(p->gid_attr_group->ndev.attrs);
p->gid_attr_group->ndev.attrs = NULL;
err_remove_gid:
sysfs_remove_group(&p->kobj, &p->gid_group);
@ -589,6 +761,9 @@ err_free_gid:
err_remove_pma:
sysfs_remove_group(&p->kobj, &pma_group);
err_put_gid_attrs:
kobject_put(&p->gid_attr_group->kobj);
err_put:
kobject_put(&p->kobj);
return ret;
@ -797,6 +972,11 @@ static void free_port_list_attributes(struct ib_device *device)
sysfs_remove_group(p, &pma_group);
sysfs_remove_group(p, &port->pkey_group);
sysfs_remove_group(p, &port->gid_group);
sysfs_remove_group(&port->gid_attr_group->kobj,
&port->gid_attr_group->ndev);
sysfs_remove_group(&port->gid_attr_group->kobj,
&port->gid_attr_group->type);
kobject_put(&port->gid_attr_group->kobj);
kobject_put(p);
}