Commit 054239f4 authored by Jason Gunthorpe's avatar Jason Gunthorpe

RDMA/core: Expose the ib port sysfs attribute machinery

Other things outside the core code are creating attributes against the
port. This patch exposes the basic machinery to do this.

The ib_port_attribute type allows creating groups of attributes attatched
to the port and comes with the usual machinery to do this.

Link: https://lore.kernel.org/r/5c4aeae57f6fa7c59a1d6d1c5506069516ae9bbf.1623427137.git.leonro@nvidia.comSigned-off-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent d89eb509
...@@ -44,24 +44,10 @@ ...@@ -44,24 +44,10 @@
#include <rdma/ib_pma.h> #include <rdma/ib_pma.h>
#include <rdma/ib_cache.h> #include <rdma/ib_cache.h>
#include <rdma/rdma_counter.h> #include <rdma/rdma_counter.h>
#include <rdma/ib_sysfs.h>
struct ib_port;
struct port_attribute {
struct attribute attr;
ssize_t (*show)(struct ib_port *, struct port_attribute *, char *buf);
ssize_t (*store)(struct ib_port *, struct port_attribute *,
const char *buf, size_t count);
};
#define PORT_ATTR(_name, _mode, _show, _store) \
struct port_attribute port_attr_##_name = __ATTR(_name, _mode, _show, _store)
#define PORT_ATTR_RO(_name) \
struct port_attribute port_attr_##_name = __ATTR_RO(_name)
struct port_table_attribute { struct port_table_attribute {
struct port_attribute attr; struct ib_port_attribute attr;
char name[8]; char name[8];
int index; int index;
__be16 attr_id; __be16 attr_id;
...@@ -97,7 +83,7 @@ struct hw_stats_device_attribute { ...@@ -97,7 +83,7 @@ struct hw_stats_device_attribute {
}; };
struct hw_stats_port_attribute { struct hw_stats_port_attribute {
struct port_attribute attr; struct ib_port_attribute attr;
ssize_t (*show)(struct ib_device *ibdev, struct rdma_hw_stats *stats, ssize_t (*show)(struct ib_device *ibdev, struct rdma_hw_stats *stats,
unsigned int index, unsigned int port_num, char *buf); unsigned int index, unsigned int port_num, char *buf);
ssize_t (*store)(struct ib_device *ibdev, struct rdma_hw_stats *stats, ssize_t (*store)(struct ib_device *ibdev, struct rdma_hw_stats *stats,
...@@ -119,29 +105,55 @@ struct hw_stats_port_data { ...@@ -119,29 +105,55 @@ struct hw_stats_port_data {
static ssize_t port_attr_show(struct kobject *kobj, static ssize_t port_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf) struct attribute *attr, char *buf)
{ {
struct port_attribute *port_attr = struct ib_port_attribute *port_attr =
container_of(attr, struct port_attribute, attr); container_of(attr, struct ib_port_attribute, attr);
struct ib_port *p = container_of(kobj, struct ib_port, kobj); struct ib_port *p = container_of(kobj, struct ib_port, kobj);
if (!port_attr->show) if (!port_attr->show)
return -EIO; return -EIO;
return port_attr->show(p, port_attr, buf); return port_attr->show(p->ibdev, p->port_num, port_attr, buf);
} }
static ssize_t port_attr_store(struct kobject *kobj, static ssize_t port_attr_store(struct kobject *kobj,
struct attribute *attr, struct attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct port_attribute *port_attr = struct ib_port_attribute *port_attr =
container_of(attr, struct port_attribute, attr); container_of(attr, struct ib_port_attribute, attr);
struct ib_port *p = container_of(kobj, struct ib_port, kobj); struct ib_port *p = container_of(kobj, struct ib_port, kobj);
if (!port_attr->store) if (!port_attr->store)
return -EIO; return -EIO;
return port_attr->store(p, port_attr, buf, count); return port_attr->store(p->ibdev, p->port_num, port_attr, buf, count);
} }
int ib_port_sysfs_create_groups(struct ib_device *ibdev, u32 port_num,
const struct attribute_group **groups)
{
return sysfs_create_groups(&ibdev->port_data[port_num].sysfs->kobj,
groups);
}
EXPORT_SYMBOL_GPL(ib_port_sysfs_create_groups);
void ib_port_sysfs_remove_groups(struct ib_device *ibdev, u32 port_num,
const struct attribute_group **groups)
{
return sysfs_remove_groups(&ibdev->port_data[port_num].sysfs->kobj,
groups);
}
EXPORT_SYMBOL_GPL(ib_port_sysfs_remove_groups);
struct ib_device *ib_port_sysfs_get_ibdev_kobj(struct kobject *kobj,
u32 *port_num)
{
struct ib_port *port = container_of(kobj, struct ib_port, kobj);
*port_num = port->port_num;
return port->ibdev;
}
EXPORT_SYMBOL(ib_port_sysfs_get_ibdev_kobj);
static const struct sysfs_ops port_sysfs_ops = { static const struct sysfs_ops port_sysfs_ops = {
.show = port_attr_show, .show = port_attr_show,
.store = port_attr_store .store = port_attr_store
...@@ -171,25 +183,27 @@ static ssize_t hw_stat_device_store(struct device *dev, ...@@ -171,25 +183,27 @@ static ssize_t hw_stat_device_store(struct device *dev,
count); count);
} }
static ssize_t hw_stat_port_show(struct ib_port *port, static ssize_t hw_stat_port_show(struct ib_device *ibdev, u32 port_num,
struct port_attribute *attr, char *buf) struct ib_port_attribute *attr, char *buf)
{ {
struct hw_stats_port_attribute *stat_attr = struct hw_stats_port_attribute *stat_attr =
container_of(attr, struct hw_stats_port_attribute, attr); container_of(attr, struct hw_stats_port_attribute, attr);
struct ib_port *port = ibdev->port_data[port_num].sysfs;
return stat_attr->show(port->ibdev, port->hw_stats_data->stats, return stat_attr->show(ibdev, port->hw_stats_data->stats,
stat_attr - port->hw_stats_data->attrs, stat_attr - port->hw_stats_data->attrs,
port->port_num, buf); port->port_num, buf);
} }
static ssize_t hw_stat_port_store(struct ib_port *port, static ssize_t hw_stat_port_store(struct ib_device *ibdev, u32 port_num,
struct port_attribute *attr, const char *buf, struct ib_port_attribute *attr,
size_t count) const char *buf, size_t count)
{ {
struct hw_stats_port_attribute *stat_attr = struct hw_stats_port_attribute *stat_attr =
container_of(attr, struct hw_stats_port_attribute, attr); container_of(attr, struct hw_stats_port_attribute, attr);
struct ib_port *port = ibdev->port_data[port_num].sysfs;
return stat_attr->store(port->ibdev, port->hw_stats_data->stats, return stat_attr->store(ibdev, port->hw_stats_data->stats,
stat_attr - port->hw_stats_data->attrs, stat_attr - port->hw_stats_data->attrs,
port->port_num, buf, count); port->port_num, buf, count);
} }
...@@ -197,23 +211,23 @@ static ssize_t hw_stat_port_store(struct ib_port *port, ...@@ -197,23 +211,23 @@ static ssize_t hw_stat_port_store(struct ib_port *port,
static ssize_t gid_attr_show(struct kobject *kobj, static ssize_t gid_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf) struct attribute *attr, char *buf)
{ {
struct port_attribute *port_attr = struct ib_port_attribute *port_attr =
container_of(attr, struct port_attribute, attr); container_of(attr, struct ib_port_attribute, attr);
struct ib_port *p = container_of(kobj, struct gid_attr_group, struct ib_port *p = container_of(kobj, struct gid_attr_group,
kobj)->port; kobj)->port;
if (!port_attr->show) if (!port_attr->show)
return -EIO; return -EIO;
return port_attr->show(p, port_attr, buf); return port_attr->show(p->ibdev, p->port_num, port_attr, buf);
} }
static const struct sysfs_ops gid_attr_sysfs_ops = { static const struct sysfs_ops gid_attr_sysfs_ops = {
.show = gid_attr_show .show = gid_attr_show
}; };
static ssize_t state_show(struct ib_port *p, struct port_attribute *unused, static ssize_t state_show(struct ib_device *ibdev, u32 port_num,
char *buf) struct ib_port_attribute *unused, char *buf)
{ {
struct ib_port_attr attr; struct ib_port_attr attr;
ssize_t ret; ssize_t ret;
...@@ -227,7 +241,7 @@ static ssize_t state_show(struct ib_port *p, struct port_attribute *unused, ...@@ -227,7 +241,7 @@ static ssize_t state_show(struct ib_port *p, struct port_attribute *unused,
[IB_PORT_ACTIVE_DEFER] = "ACTIVE_DEFER" [IB_PORT_ACTIVE_DEFER] = "ACTIVE_DEFER"
}; };
ret = ib_query_port(p->ibdev, p->port_num, &attr); ret = ib_query_port(ibdev, port_num, &attr);
if (ret) if (ret)
return ret; return ret;
...@@ -238,81 +252,80 @@ static ssize_t state_show(struct ib_port *p, struct port_attribute *unused, ...@@ -238,81 +252,80 @@ static ssize_t state_show(struct ib_port *p, struct port_attribute *unused,
"UNKNOWN"); "UNKNOWN");
} }
static ssize_t lid_show(struct ib_port *p, struct port_attribute *unused, static ssize_t lid_show(struct ib_device *ibdev, u32 port_num,
char *buf) struct ib_port_attribute *unused, char *buf)
{ {
struct ib_port_attr attr; struct ib_port_attr attr;
ssize_t ret; ssize_t ret;
ret = ib_query_port(p->ibdev, p->port_num, &attr); ret = ib_query_port(ibdev, port_num, &attr);
if (ret) if (ret)
return ret; return ret;
return sysfs_emit(buf, "0x%x\n", attr.lid); return sysfs_emit(buf, "0x%x\n", attr.lid);
} }
static ssize_t lid_mask_count_show(struct ib_port *p, static ssize_t lid_mask_count_show(struct ib_device *ibdev, u32 port_num,
struct port_attribute *unused, struct ib_port_attribute *unused, char *buf)
char *buf)
{ {
struct ib_port_attr attr; struct ib_port_attr attr;
ssize_t ret; ssize_t ret;
ret = ib_query_port(p->ibdev, p->port_num, &attr); ret = ib_query_port(ibdev, port_num, &attr);
if (ret) if (ret)
return ret; return ret;
return sysfs_emit(buf, "%d\n", attr.lmc); return sysfs_emit(buf, "%d\n", attr.lmc);
} }
static ssize_t sm_lid_show(struct ib_port *p, struct port_attribute *unused, static ssize_t sm_lid_show(struct ib_device *ibdev, u32 port_num,
char *buf) struct ib_port_attribute *unused, char *buf)
{ {
struct ib_port_attr attr; struct ib_port_attr attr;
ssize_t ret; ssize_t ret;
ret = ib_query_port(p->ibdev, p->port_num, &attr); ret = ib_query_port(ibdev, port_num, &attr);
if (ret) if (ret)
return ret; return ret;
return sysfs_emit(buf, "0x%x\n", attr.sm_lid); return sysfs_emit(buf, "0x%x\n", attr.sm_lid);
} }
static ssize_t sm_sl_show(struct ib_port *p, struct port_attribute *unused, static ssize_t sm_sl_show(struct ib_device *ibdev, u32 port_num,
char *buf) struct ib_port_attribute *unused, char *buf)
{ {
struct ib_port_attr attr; struct ib_port_attr attr;
ssize_t ret; ssize_t ret;
ret = ib_query_port(p->ibdev, p->port_num, &attr); ret = ib_query_port(ibdev, port_num, &attr);
if (ret) if (ret)
return ret; return ret;
return sysfs_emit(buf, "%d\n", attr.sm_sl); return sysfs_emit(buf, "%d\n", attr.sm_sl);
} }
static ssize_t cap_mask_show(struct ib_port *p, struct port_attribute *unused, static ssize_t cap_mask_show(struct ib_device *ibdev, u32 port_num,
char *buf) struct ib_port_attribute *unused, char *buf)
{ {
struct ib_port_attr attr; struct ib_port_attr attr;
ssize_t ret; ssize_t ret;
ret = ib_query_port(p->ibdev, p->port_num, &attr); ret = ib_query_port(ibdev, port_num, &attr);
if (ret) if (ret)
return ret; return ret;
return sysfs_emit(buf, "0x%08x\n", attr.port_cap_flags); return sysfs_emit(buf, "0x%08x\n", attr.port_cap_flags);
} }
static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused, static ssize_t rate_show(struct ib_device *ibdev, u32 port_num,
char *buf) struct ib_port_attribute *unused, char *buf)
{ {
struct ib_port_attr attr; struct ib_port_attr attr;
char *speed = ""; char *speed = "";
int rate; /* in deci-Gb/sec */ int rate; /* in deci-Gb/sec */
ssize_t ret; ssize_t ret;
ret = ib_query_port(p->ibdev, p->port_num, &attr); ret = ib_query_port(ibdev, port_num, &attr);
if (ret) if (ret)
return ret; return ret;
...@@ -379,14 +392,14 @@ static const char *phys_state_to_str(enum ib_port_phys_state phys_state) ...@@ -379,14 +392,14 @@ static const char *phys_state_to_str(enum ib_port_phys_state phys_state)
return "<unknown>"; return "<unknown>";
} }
static ssize_t phys_state_show(struct ib_port *p, struct port_attribute *unused, static ssize_t phys_state_show(struct ib_device *ibdev, u32 port_num,
char *buf) struct ib_port_attribute *unused, char *buf)
{ {
struct ib_port_attr attr; struct ib_port_attr attr;
ssize_t ret; ssize_t ret;
ret = ib_query_port(p->ibdev, p->port_num, &attr); ret = ib_query_port(ibdev, port_num, &attr);
if (ret) if (ret)
return ret; return ret;
...@@ -394,12 +407,12 @@ static ssize_t phys_state_show(struct ib_port *p, struct port_attribute *unused, ...@@ -394,12 +407,12 @@ static ssize_t phys_state_show(struct ib_port *p, struct port_attribute *unused,
phys_state_to_str(attr.phys_state)); phys_state_to_str(attr.phys_state));
} }
static ssize_t link_layer_show(struct ib_port *p, struct port_attribute *unused, static ssize_t link_layer_show(struct ib_device *ibdev, u32 port_num,
char *buf) struct ib_port_attribute *unused, char *buf)
{ {
const char *output; const char *output;
switch (rdma_port_get_link_layer(p->ibdev, p->port_num)) { switch (rdma_port_get_link_layer(ibdev, port_num)) {
case IB_LINK_LAYER_INFINIBAND: case IB_LINK_LAYER_INFINIBAND:
output = "InfiniBand"; output = "InfiniBand";
break; break;
...@@ -414,26 +427,26 @@ static ssize_t link_layer_show(struct ib_port *p, struct port_attribute *unused, ...@@ -414,26 +427,26 @@ static ssize_t link_layer_show(struct ib_port *p, struct port_attribute *unused,
return sysfs_emit(buf, "%s\n", output); return sysfs_emit(buf, "%s\n", output);
} }
static PORT_ATTR_RO(state); static IB_PORT_ATTR_RO(state);
static PORT_ATTR_RO(lid); static IB_PORT_ATTR_RO(lid);
static PORT_ATTR_RO(lid_mask_count); static IB_PORT_ATTR_RO(lid_mask_count);
static PORT_ATTR_RO(sm_lid); static IB_PORT_ATTR_RO(sm_lid);
static PORT_ATTR_RO(sm_sl); static IB_PORT_ATTR_RO(sm_sl);
static PORT_ATTR_RO(cap_mask); static IB_PORT_ATTR_RO(cap_mask);
static PORT_ATTR_RO(rate); static IB_PORT_ATTR_RO(rate);
static PORT_ATTR_RO(phys_state); static IB_PORT_ATTR_RO(phys_state);
static PORT_ATTR_RO(link_layer); static IB_PORT_ATTR_RO(link_layer);
static struct attribute *port_default_attrs[] = { static struct attribute *port_default_attrs[] = {
&port_attr_state.attr, &ib_port_attr_state.attr,
&port_attr_lid.attr, &ib_port_attr_lid.attr,
&port_attr_lid_mask_count.attr, &ib_port_attr_lid_mask_count.attr,
&port_attr_sm_lid.attr, &ib_port_attr_sm_lid.attr,
&port_attr_sm_sl.attr, &ib_port_attr_sm_sl.attr,
&port_attr_cap_mask.attr, &ib_port_attr_cap_mask.attr,
&port_attr_rate.attr, &ib_port_attr_rate.attr,
&port_attr_phys_state.attr, &ib_port_attr_phys_state.attr,
&port_attr_link_layer.attr, &ib_port_attr_link_layer.attr,
NULL NULL
}; };
...@@ -457,7 +470,8 @@ static ssize_t print_gid_type(const struct ib_gid_attr *gid_attr, char *buf) ...@@ -457,7 +470,8 @@ static ssize_t print_gid_type(const struct ib_gid_attr *gid_attr, char *buf)
} }
static ssize_t _show_port_gid_attr( static ssize_t _show_port_gid_attr(
struct ib_port *p, struct port_attribute *attr, char *buf, struct ib_device *ibdev, u32 port_num, struct ib_port_attribute *attr,
char *buf,
ssize_t (*print)(const struct ib_gid_attr *gid_attr, char *buf)) ssize_t (*print)(const struct ib_gid_attr *gid_attr, char *buf))
{ {
struct port_table_attribute *tab_attr = struct port_table_attribute *tab_attr =
...@@ -465,7 +479,7 @@ static ssize_t _show_port_gid_attr( ...@@ -465,7 +479,7 @@ static ssize_t _show_port_gid_attr(
const struct ib_gid_attr *gid_attr; const struct ib_gid_attr *gid_attr;
ssize_t ret; ssize_t ret;
gid_attr = rdma_get_gid_attr(p->ibdev, p->port_num, tab_attr->index); gid_attr = rdma_get_gid_attr(ibdev, port_num, tab_attr->index);
if (IS_ERR(gid_attr)) if (IS_ERR(gid_attr))
/* -EINVAL is returned for user space compatibility reasons. */ /* -EINVAL is returned for user space compatibility reasons. */
return -EINVAL; return -EINVAL;
...@@ -475,15 +489,15 @@ static ssize_t _show_port_gid_attr( ...@@ -475,15 +489,15 @@ static ssize_t _show_port_gid_attr(
return ret; return ret;
} }
static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr, static ssize_t show_port_gid(struct ib_device *ibdev, u32 port_num,
char *buf) struct ib_port_attribute *attr, char *buf)
{ {
struct port_table_attribute *tab_attr = struct port_table_attribute *tab_attr =
container_of(attr, struct port_table_attribute, attr); container_of(attr, struct port_table_attribute, attr);
const struct ib_gid_attr *gid_attr; const struct ib_gid_attr *gid_attr;
int len; int len;
gid_attr = rdma_get_gid_attr(p->ibdev, p->port_num, tab_attr->index); gid_attr = rdma_get_gid_attr(ibdev, port_num, tab_attr->index);
if (IS_ERR(gid_attr)) { if (IS_ERR(gid_attr)) {
const union ib_gid zgid = {}; const union ib_gid zgid = {};
...@@ -504,28 +518,30 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr, ...@@ -504,28 +518,30 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
return len; return len;
} }
static ssize_t show_port_gid_attr_ndev(struct ib_port *p, static ssize_t show_port_gid_attr_ndev(struct ib_device *ibdev, u32 port_num,
struct port_attribute *attr, char *buf) struct ib_port_attribute *attr,
char *buf)
{ {
return _show_port_gid_attr(p, attr, buf, print_ndev); return _show_port_gid_attr(ibdev, port_num, attr, buf, print_ndev);
} }
static ssize_t show_port_gid_attr_gid_type(struct ib_port *p, static ssize_t show_port_gid_attr_gid_type(struct ib_device *ibdev,
struct port_attribute *attr, u32 port_num,
struct ib_port_attribute *attr,
char *buf) char *buf)
{ {
return _show_port_gid_attr(p, attr, buf, print_gid_type); return _show_port_gid_attr(ibdev, port_num, attr, buf, print_gid_type);
} }
static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr, static ssize_t show_port_pkey(struct ib_device *ibdev, u32 port_num,
char *buf) struct ib_port_attribute *attr, char *buf)
{ {
struct port_table_attribute *tab_attr = struct port_table_attribute *tab_attr =
container_of(attr, struct port_table_attribute, attr); container_of(attr, struct port_table_attribute, attr);
u16 pkey; u16 pkey;
int ret; int ret;
ret = ib_query_pkey(p->ibdev, p->port_num, tab_attr->index, &pkey); ret = ib_query_pkey(ibdev, port_num, tab_attr->index, &pkey);
if (ret) if (ret)
return ret; return ret;
...@@ -594,8 +610,8 @@ static int get_perf_mad(struct ib_device *dev, int port_num, __be16 attr, ...@@ -594,8 +610,8 @@ static int get_perf_mad(struct ib_device *dev, int port_num, __be16 attr,
return ret; return ret;
} }
static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr, static ssize_t show_pma_counter(struct ib_device *ibdev, u32 port_num,
char *buf) struct ib_port_attribute *attr, char *buf)
{ {
struct port_table_attribute *tab_attr = struct port_table_attribute *tab_attr =
container_of(attr, struct port_table_attribute, attr); container_of(attr, struct port_table_attribute, attr);
...@@ -605,7 +621,7 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr, ...@@ -605,7 +621,7 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
u8 data[8]; u8 data[8];
int len; int len;
ret = get_perf_mad(p->ibdev, p->port_num, tab_attr->attr_id, &data, ret = get_perf_mad(ibdev, port_num, tab_attr->attr_id, &data,
40 + offset / 8, sizeof(data)); 40 + offset / 8, sizeof(data));
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1077,10 +1093,11 @@ struct rdma_hw_stats *ib_get_hw_stats_port(struct ib_device *ibdev, ...@@ -1077,10 +1093,11 @@ struct rdma_hw_stats *ib_get_hw_stats_port(struct ib_device *ibdev,
return ibdev->port_data[port_num].sysfs->hw_stats_data->stats; return ibdev->port_data[port_num].sysfs->hw_stats_data->stats;
} }
static int alloc_port_table_group( static int
const char *name, struct attribute_group *group, alloc_port_table_group(const char *name, struct attribute_group *group,
struct port_table_attribute *attrs, size_t num, struct port_table_attribute *attrs, size_t num,
ssize_t (*show)(struct ib_port *, struct port_attribute *, char *buf)) ssize_t (*show)(struct ib_device *ibdev, u32 port_num,
struct ib_port_attribute *, char *buf))
{ {
struct attribute **attr_list; struct attribute **attr_list;
int i; int i;
......
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (c) 2021 Mellanox Technologies Ltd. All rights reserved.
*/
#ifndef DEF_RDMA_IB_SYSFS_H
#define DEF_RDMA_IB_SYSFS_H
#include <linux/sysfs.h>
struct ib_device;
struct ib_port_attribute {
struct attribute attr;
ssize_t (*show)(struct ib_device *ibdev, u32 port_num,
struct ib_port_attribute *attr, char *buf);
ssize_t (*store)(struct ib_device *ibdev, u32 port_num,
struct ib_port_attribute *attr, const char *buf,
size_t count);
};
#define IB_PORT_ATTR_RW(_name) \
struct ib_port_attribute ib_port_attr_##_name = __ATTR_RW(_name)
#define IB_PORT_ATTR_ADMIN_RW(_name) \
struct ib_port_attribute ib_port_attr_##_name = \
__ATTR_RW_MODE(_name, 0600)
#define IB_PORT_ATTR_RO(_name) \
struct ib_port_attribute ib_port_attr_##_name = __ATTR_RO(_name)
#define IB_PORT_ATTR_WO(_name) \
struct ib_port_attribute ib_port_attr_##_name = __ATTR_WO(_name)
int ib_port_sysfs_create_groups(struct ib_device *ibdev, u32 port_num,
const struct attribute_group **groups);
void ib_port_sysfs_remove_groups(struct ib_device *ibdev, u32 port_num,
const struct attribute_group **groups);
struct ib_device *ib_port_sysfs_get_ibdev_kobj(struct kobject *kobj,
u32 *port_num);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment