Skip to content

Commit 5e2ddd1

Browse files
aharonl-nvidiajgunthorpe
authored andcommitted
RDMA/counter: Add optional counter support
An optional counter is a driver-specific counter that may be dynamically enabled/disabled. This enhancement allows drivers to expose counters which are, for example, mutually exclusive and cannot be enabled at the same time, counters that might degrades performance, optional debug counters, etc. Optional counters are marked with IB_STAT_FLAG_OPTIONAL flag. They are not exported in sysfs, and must be at the end of all stats, otherwise the attr->show() in sysfs would get wrong indexes for hwcounters that are behind optional counters. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Aharon Landau <[email protected]> Signed-off-by: Neta Ostrovsky <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Mark Zhang <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 0dc8968 commit 5e2ddd1

File tree

5 files changed

+74
-10
lines changed

5 files changed

+74
-10
lines changed

drivers/infiniband/core/counters.c

+32
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,38 @@ static int __rdma_counter_bind_qp(struct rdma_counter *counter,
106106
return ret;
107107
}
108108

109+
int rdma_counter_modify(struct ib_device *dev, u32 port,
110+
unsigned int index, bool enable)
111+
{
112+
struct rdma_hw_stats *stats;
113+
int ret = 0;
114+
115+
if (!dev->ops.modify_hw_stat)
116+
return -EOPNOTSUPP;
117+
118+
stats = ib_get_hw_stats_port(dev, port);
119+
if (!stats || index >= stats->num_counters ||
120+
!(stats->descs[index].flags & IB_STAT_FLAG_OPTIONAL))
121+
return -EINVAL;
122+
123+
mutex_lock(&stats->lock);
124+
125+
if (enable != test_bit(index, stats->is_disabled))
126+
goto out;
127+
128+
ret = dev->ops.modify_hw_stat(dev, port, index, enable);
129+
if (ret)
130+
goto out;
131+
132+
if (enable)
133+
clear_bit(index, stats->is_disabled);
134+
else
135+
set_bit(index, stats->is_disabled);
136+
out:
137+
mutex_unlock(&stats->lock);
138+
return ret;
139+
}
140+
109141
static struct rdma_counter *alloc_and_bind(struct ib_device *dev, u32 port,
110142
struct ib_qp *qp,
111143
enum rdma_nl_counter_mode mode)

drivers/infiniband/core/device.c

+1
Original file line numberDiff line numberDiff line change
@@ -2676,6 +2676,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
26762676
SET_DEVICE_OP(dev_ops, modify_cq);
26772677
SET_DEVICE_OP(dev_ops, modify_device);
26782678
SET_DEVICE_OP(dev_ops, modify_flow_action_esp);
2679+
SET_DEVICE_OP(dev_ops, modify_hw_stat);
26792680
SET_DEVICE_OP(dev_ops, modify_port);
26802681
SET_DEVICE_OP(dev_ops, modify_qp);
26812682
SET_DEVICE_OP(dev_ops, modify_srq);

drivers/infiniband/core/sysfs.c

+26-10
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,8 @@ int ib_setup_device_attrs(struct ib_device *ibdev)
934934
{
935935
struct hw_stats_device_attribute *attr;
936936
struct hw_stats_device_data *data;
937-
int i, ret;
937+
bool opstat_skipped = false;
938+
int i, ret, pos = 0;
938939

939940
data = alloc_hw_stats_device(ibdev);
940941
if (IS_ERR(data)) {
@@ -955,24 +956,31 @@ int ib_setup_device_attrs(struct ib_device *ibdev)
955956
data->stats->timestamp = jiffies;
956957

957958
for (i = 0; i < data->stats->num_counters; i++) {
958-
attr = &data->attrs[i];
959+
if (data->stats->descs[i].flags & IB_STAT_FLAG_OPTIONAL) {
960+
opstat_skipped = true;
961+
continue;
962+
}
963+
964+
WARN_ON(opstat_skipped);
965+
attr = &data->attrs[pos];
959966
sysfs_attr_init(&attr->attr.attr);
960967
attr->attr.attr.name = data->stats->descs[i].name;
961968
attr->attr.attr.mode = 0444;
962969
attr->attr.show = hw_stat_device_show;
963970
attr->show = show_hw_stats;
964-
data->group.attrs[i] = &attr->attr.attr;
971+
data->group.attrs[pos] = &attr->attr.attr;
972+
pos++;
965973
}
966974

967-
attr = &data->attrs[i];
975+
attr = &data->attrs[pos];
968976
sysfs_attr_init(&attr->attr.attr);
969977
attr->attr.attr.name = "lifespan";
970978
attr->attr.attr.mode = 0644;
971979
attr->attr.show = hw_stat_device_show;
972980
attr->show = show_stats_lifespan;
973981
attr->attr.store = hw_stat_device_store;
974982
attr->store = set_stats_lifespan;
975-
data->group.attrs[i] = &attr->attr.attr;
983+
data->group.attrs[pos] = &attr->attr.attr;
976984
for (i = 0; i != ARRAY_SIZE(ibdev->groups); i++)
977985
if (!ibdev->groups[i]) {
978986
ibdev->groups[i] = &data->group;
@@ -1027,7 +1035,8 @@ static int setup_hw_port_stats(struct ib_port *port,
10271035
{
10281036
struct hw_stats_port_attribute *attr;
10291037
struct hw_stats_port_data *data;
1030-
int i, ret;
1038+
bool opstat_skipped = false;
1039+
int i, ret, pos = 0;
10311040

10321041
data = alloc_hw_stats_port(port, group);
10331042
if (IS_ERR(data))
@@ -1045,24 +1054,31 @@ static int setup_hw_port_stats(struct ib_port *port,
10451054
data->stats->timestamp = jiffies;
10461055

10471056
for (i = 0; i < data->stats->num_counters; i++) {
1048-
attr = &data->attrs[i];
1057+
if (data->stats->descs[i].flags & IB_STAT_FLAG_OPTIONAL) {
1058+
opstat_skipped = true;
1059+
continue;
1060+
}
1061+
1062+
WARN_ON(opstat_skipped);
1063+
attr = &data->attrs[pos];
10491064
sysfs_attr_init(&attr->attr.attr);
10501065
attr->attr.attr.name = data->stats->descs[i].name;
10511066
attr->attr.attr.mode = 0444;
10521067
attr->attr.show = hw_stat_port_show;
10531068
attr->show = show_hw_stats;
1054-
group->attrs[i] = &attr->attr.attr;
1069+
group->attrs[pos] = &attr->attr.attr;
1070+
pos++;
10551071
}
10561072

1057-
attr = &data->attrs[i];
1073+
attr = &data->attrs[pos];
10581074
sysfs_attr_init(&attr->attr.attr);
10591075
attr->attr.attr.name = "lifespan";
10601076
attr->attr.attr.mode = 0644;
10611077
attr->attr.show = hw_stat_port_show;
10621078
attr->show = show_stats_lifespan;
10631079
attr->attr.store = hw_stat_port_store;
10641080
attr->store = set_stats_lifespan;
1065-
group->attrs[i] = &attr->attr.attr;
1081+
group->attrs[pos] = &attr->attr.attr;
10661082

10671083
port->hw_stats_data = data;
10681084
return 0;

include/rdma/ib_verbs.h

+13
Original file line numberDiff line numberDiff line change
@@ -545,12 +545,18 @@ enum ib_port_speed {
545545
IB_SPEED_NDR = 128,
546546
};
547547

548+
enum ib_stat_flag {
549+
IB_STAT_FLAG_OPTIONAL = 1 << 0,
550+
};
551+
548552
/**
549553
* struct rdma_stat_desc
550554
* @name - The name of the counter
555+
* @flags - Flags of the counter; For example, IB_STAT_FLAG_OPTIONAL
551556
*/
552557
struct rdma_stat_desc {
553558
const char *name;
559+
unsigned int flags;
554560
};
555561

556562
/**
@@ -2562,6 +2568,13 @@ struct ib_device_ops {
25622568
int (*get_hw_stats)(struct ib_device *device,
25632569
struct rdma_hw_stats *stats, u32 port, int index);
25642570

2571+
/**
2572+
* modify_hw_stat - Modify the counter configuration
2573+
* @enable: true/false when enable/disable a counter
2574+
* Return codes - 0 on success or error code otherwise.
2575+
*/
2576+
int (*modify_hw_stat)(struct ib_device *device, u32 port,
2577+
unsigned int counter_index, bool enable);
25652578
/**
25662579
* Allows rdma drivers to add their own restrack attributes.
25672580
*/

include/rdma/rdma_counter.h

+2
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,6 @@ int rdma_counter_get_mode(struct ib_device *dev, u32 port,
6363
enum rdma_nl_counter_mode *mode,
6464
enum rdma_nl_counter_mask *mask);
6565

66+
int rdma_counter_modify(struct ib_device *dev, u32 port,
67+
unsigned int index, bool enable);
6668
#endif /* _RDMA_COUNTER_H_ */

0 commit comments

Comments
 (0)