1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
3 * Copyright (c) 2019 Mellanox Technologies. All rights reserved.
5 #include <rdma/ib_verbs.h>
6 #include <rdma/rdma_counter.h>
11 #define ALL_AUTO_MODE_MASKS (RDMA_COUNTER_MASK_QP_TYPE | RDMA_COUNTER_MASK_PID)
13 static int __counter_set_mode(struct rdma_counter_mode
*curr
,
14 enum rdma_nl_counter_mode new_mode
,
15 enum rdma_nl_counter_mask new_mask
)
17 if ((new_mode
== RDMA_COUNTER_MODE_AUTO
) &&
18 ((new_mask
& (~ALL_AUTO_MODE_MASKS
)) ||
19 (curr
->mode
!= RDMA_COUNTER_MODE_NONE
)))
22 curr
->mode
= new_mode
;
23 curr
->mask
= new_mask
;
28 * rdma_counter_set_auto_mode() - Turn on/off per-port auto mode
30 * When @on is true, the @mask must be set; When @on is false, it goes
31 * into manual mode if there's any counter, so that the user is able to
32 * manually access them.
34 int rdma_counter_set_auto_mode(struct ib_device
*dev
, u8 port
,
35 bool on
, enum rdma_nl_counter_mask mask
)
37 struct rdma_port_counter
*port_counter
;
40 port_counter
= &dev
->port_data
[port
].port_counter
;
41 if (!port_counter
->hstats
)
44 mutex_lock(&port_counter
->lock
);
46 ret
= __counter_set_mode(&port_counter
->mode
,
47 RDMA_COUNTER_MODE_AUTO
, mask
);
49 if (port_counter
->mode
.mode
!= RDMA_COUNTER_MODE_AUTO
) {
54 if (port_counter
->num_counters
)
55 ret
= __counter_set_mode(&port_counter
->mode
,
56 RDMA_COUNTER_MODE_MANUAL
, 0);
58 ret
= __counter_set_mode(&port_counter
->mode
,
59 RDMA_COUNTER_MODE_NONE
, 0);
63 mutex_unlock(&port_counter
->lock
);
67 static void auto_mode_init_counter(struct rdma_counter
*counter
,
68 const struct ib_qp
*qp
,
69 enum rdma_nl_counter_mask new_mask
)
71 struct auto_mode_param
*param
= &counter
->mode
.param
;
73 counter
->mode
.mode
= RDMA_COUNTER_MODE_AUTO
;
74 counter
->mode
.mask
= new_mask
;
76 if (new_mask
& RDMA_COUNTER_MASK_QP_TYPE
)
77 param
->qp_type
= qp
->qp_type
;
80 static int __rdma_counter_bind_qp(struct rdma_counter
*counter
,
88 if (!qp
->device
->ops
.counter_bind_qp
)
91 mutex_lock(&counter
->lock
);
92 ret
= qp
->device
->ops
.counter_bind_qp(counter
, qp
);
93 mutex_unlock(&counter
->lock
);
98 static struct rdma_counter
*alloc_and_bind(struct ib_device
*dev
, u8 port
,
100 enum rdma_nl_counter_mode mode
)
102 struct rdma_port_counter
*port_counter
;
103 struct rdma_counter
*counter
;
106 if (!dev
->ops
.counter_dealloc
|| !dev
->ops
.counter_alloc_stats
)
109 counter
= kzalloc(sizeof(*counter
), GFP_KERNEL
);
113 counter
->device
= dev
;
114 counter
->port
= port
;
116 rdma_restrack_new(&counter
->res
, RDMA_RESTRACK_COUNTER
);
117 counter
->stats
= dev
->ops
.counter_alloc_stats(counter
);
121 port_counter
= &dev
->port_data
[port
].port_counter
;
122 mutex_lock(&port_counter
->lock
);
124 case RDMA_COUNTER_MODE_MANUAL
:
125 ret
= __counter_set_mode(&port_counter
->mode
,
126 RDMA_COUNTER_MODE_MANUAL
, 0);
128 mutex_unlock(&port_counter
->lock
);
132 case RDMA_COUNTER_MODE_AUTO
:
133 auto_mode_init_counter(counter
, qp
, port_counter
->mode
.mask
);
137 mutex_unlock(&port_counter
->lock
);
141 port_counter
->num_counters
++;
142 mutex_unlock(&port_counter
->lock
);
144 counter
->mode
.mode
= mode
;
145 kref_init(&counter
->kref
);
146 mutex_init(&counter
->lock
);
148 ret
= __rdma_counter_bind_qp(counter
, qp
);
152 rdma_restrack_parent_name(&counter
->res
, &qp
->res
);
153 rdma_restrack_add(&counter
->res
);
157 kfree(counter
->stats
);
159 rdma_restrack_put(&counter
->res
);
164 static void rdma_counter_free(struct rdma_counter
*counter
)
166 struct rdma_port_counter
*port_counter
;
168 port_counter
= &counter
->device
->port_data
[counter
->port
].port_counter
;
169 mutex_lock(&port_counter
->lock
);
170 port_counter
->num_counters
--;
171 if (!port_counter
->num_counters
&&
172 (port_counter
->mode
.mode
== RDMA_COUNTER_MODE_MANUAL
))
173 __counter_set_mode(&port_counter
->mode
, RDMA_COUNTER_MODE_NONE
,
176 mutex_unlock(&port_counter
->lock
);
178 rdma_restrack_del(&counter
->res
);
179 kfree(counter
->stats
);
183 static bool auto_mode_match(struct ib_qp
*qp
, struct rdma_counter
*counter
,
184 enum rdma_nl_counter_mask auto_mask
)
186 struct auto_mode_param
*param
= &counter
->mode
.param
;
189 if (auto_mask
& RDMA_COUNTER_MASK_QP_TYPE
)
190 match
&= (param
->qp_type
== qp
->qp_type
);
192 if (auto_mask
& RDMA_COUNTER_MASK_PID
)
193 match
&= (task_pid_nr(counter
->res
.task
) ==
194 task_pid_nr(qp
->res
.task
));
199 static int __rdma_counter_unbind_qp(struct ib_qp
*qp
)
201 struct rdma_counter
*counter
= qp
->counter
;
204 if (!qp
->device
->ops
.counter_unbind_qp
)
207 mutex_lock(&counter
->lock
);
208 ret
= qp
->device
->ops
.counter_unbind_qp(qp
);
209 mutex_unlock(&counter
->lock
);
214 static void counter_history_stat_update(struct rdma_counter
*counter
)
216 struct ib_device
*dev
= counter
->device
;
217 struct rdma_port_counter
*port_counter
;
220 port_counter
= &dev
->port_data
[counter
->port
].port_counter
;
221 if (!port_counter
->hstats
)
224 rdma_counter_query_stats(counter
);
226 for (i
= 0; i
< counter
->stats
->num_counters
; i
++)
227 port_counter
->hstats
->value
[i
] += counter
->stats
->value
[i
];
231 * rdma_get_counter_auto_mode - Find the counter that @qp should be bound
234 * Return: The counter (with ref-count increased) if found
236 static struct rdma_counter
*rdma_get_counter_auto_mode(struct ib_qp
*qp
,
239 struct rdma_port_counter
*port_counter
;
240 struct rdma_counter
*counter
= NULL
;
241 struct ib_device
*dev
= qp
->device
;
242 struct rdma_restrack_entry
*res
;
243 struct rdma_restrack_root
*rt
;
244 unsigned long id
= 0;
246 port_counter
= &dev
->port_data
[port
].port_counter
;
247 rt
= &dev
->res
[RDMA_RESTRACK_COUNTER
];
249 xa_for_each(&rt
->xa
, id
, res
) {
250 counter
= container_of(res
, struct rdma_counter
, res
);
251 if ((counter
->device
!= qp
->device
) || (counter
->port
!= port
))
254 if (auto_mode_match(qp
, counter
, port_counter
->mode
.mask
))
260 if (counter
&& !kref_get_unless_zero(&counter
->kref
))
267 static void counter_release(struct kref
*kref
)
269 struct rdma_counter
*counter
;
271 counter
= container_of(kref
, struct rdma_counter
, kref
);
272 counter_history_stat_update(counter
);
273 counter
->device
->ops
.counter_dealloc(counter
);
274 rdma_counter_free(counter
);
278 * rdma_counter_bind_qp_auto - Check and bind the QP to a counter base on
281 int rdma_counter_bind_qp_auto(struct ib_qp
*qp
, u8 port
)
283 struct rdma_port_counter
*port_counter
;
284 struct ib_device
*dev
= qp
->device
;
285 struct rdma_counter
*counter
;
288 if (!rdma_restrack_is_tracked(&qp
->res
) || rdma_is_kernel_res(&qp
->res
))
291 if (!rdma_is_port_valid(dev
, port
))
294 port_counter
= &dev
->port_data
[port
].port_counter
;
295 if (port_counter
->mode
.mode
!= RDMA_COUNTER_MODE_AUTO
)
298 counter
= rdma_get_counter_auto_mode(qp
, port
);
300 ret
= __rdma_counter_bind_qp(counter
, qp
);
302 kref_put(&counter
->kref
, counter_release
);
306 counter
= alloc_and_bind(dev
, port
, qp
, RDMA_COUNTER_MODE_AUTO
);
315 * rdma_counter_unbind_qp - Unbind a qp from a counter
317 * true - Decrease the counter ref-count anyway (e.g., qp destroy)
319 int rdma_counter_unbind_qp(struct ib_qp
*qp
, bool force
)
321 struct rdma_counter
*counter
= qp
->counter
;
327 ret
= __rdma_counter_unbind_qp(qp
);
331 kref_put(&counter
->kref
, counter_release
);
335 int rdma_counter_query_stats(struct rdma_counter
*counter
)
337 struct ib_device
*dev
= counter
->device
;
340 if (!dev
->ops
.counter_update_stats
)
343 mutex_lock(&counter
->lock
);
344 ret
= dev
->ops
.counter_update_stats(counter
);
345 mutex_unlock(&counter
->lock
);
350 static u64
get_running_counters_hwstat_sum(struct ib_device
*dev
,
353 struct rdma_restrack_entry
*res
;
354 struct rdma_restrack_root
*rt
;
355 struct rdma_counter
*counter
;
356 unsigned long id
= 0;
359 rt
= &dev
->res
[RDMA_RESTRACK_COUNTER
];
361 xa_for_each(&rt
->xa
, id
, res
) {
362 if (!rdma_restrack_get(res
))
367 counter
= container_of(res
, struct rdma_counter
, res
);
368 if ((counter
->device
!= dev
) || (counter
->port
!= port
) ||
369 rdma_counter_query_stats(counter
))
372 sum
+= counter
->stats
->value
[index
];
376 rdma_restrack_put(res
);
384 * rdma_counter_get_hwstat_value() - Get the sum value of all counters on a
385 * specific port, including the running ones and history data
387 u64
rdma_counter_get_hwstat_value(struct ib_device
*dev
, u8 port
, u32 index
)
389 struct rdma_port_counter
*port_counter
;
392 port_counter
= &dev
->port_data
[port
].port_counter
;
393 if (!port_counter
->hstats
)
396 sum
= get_running_counters_hwstat_sum(dev
, port
, index
);
397 sum
+= port_counter
->hstats
->value
[index
];
402 static struct ib_qp
*rdma_counter_get_qp(struct ib_device
*dev
, u32 qp_num
)
404 struct rdma_restrack_entry
*res
= NULL
;
405 struct ib_qp
*qp
= NULL
;
407 res
= rdma_restrack_get_byid(dev
, RDMA_RESTRACK_QP
, qp_num
);
411 qp
= container_of(res
, struct ib_qp
, res
);
412 if (qp
->qp_type
== IB_QPT_RAW_PACKET
&& !capable(CAP_NET_RAW
))
418 rdma_restrack_put(res
);
422 static struct rdma_counter
*rdma_get_counter_by_id(struct ib_device
*dev
,
425 struct rdma_restrack_entry
*res
;
426 struct rdma_counter
*counter
;
428 res
= rdma_restrack_get_byid(dev
, RDMA_RESTRACK_COUNTER
, counter_id
);
432 counter
= container_of(res
, struct rdma_counter
, res
);
433 kref_get(&counter
->kref
);
434 rdma_restrack_put(res
);
440 * rdma_counter_bind_qpn() - Bind QP @qp_num to counter @counter_id
442 int rdma_counter_bind_qpn(struct ib_device
*dev
, u8 port
,
443 u32 qp_num
, u32 counter_id
)
445 struct rdma_port_counter
*port_counter
;
446 struct rdma_counter
*counter
;
450 port_counter
= &dev
->port_data
[port
].port_counter
;
451 if (port_counter
->mode
.mode
== RDMA_COUNTER_MODE_AUTO
)
454 qp
= rdma_counter_get_qp(dev
, qp_num
);
458 counter
= rdma_get_counter_by_id(dev
, counter_id
);
464 if (rdma_is_kernel_res(&counter
->res
) != rdma_is_kernel_res(&qp
->res
)) {
469 if ((counter
->device
!= qp
->device
) || (counter
->port
!= qp
->port
)) {
474 ret
= __rdma_counter_bind_qp(counter
, qp
);
478 rdma_restrack_put(&qp
->res
);
482 kref_put(&counter
->kref
, counter_release
);
484 rdma_restrack_put(&qp
->res
);
489 * rdma_counter_bind_qpn_alloc() - Alloc a counter and bind QP @qp_num to it
490 * The id of new counter is returned in @counter_id
492 int rdma_counter_bind_qpn_alloc(struct ib_device
*dev
, u8 port
,
493 u32 qp_num
, u32
*counter_id
)
495 struct rdma_port_counter
*port_counter
;
496 struct rdma_counter
*counter
;
500 if (!rdma_is_port_valid(dev
, port
))
503 port_counter
= &dev
->port_data
[port
].port_counter
;
504 if (!port_counter
->hstats
)
507 if (port_counter
->mode
.mode
== RDMA_COUNTER_MODE_AUTO
)
510 qp
= rdma_counter_get_qp(dev
, qp_num
);
514 if (rdma_is_port_valid(dev
, qp
->port
) && (qp
->port
!= port
)) {
519 counter
= alloc_and_bind(dev
, port
, qp
, RDMA_COUNTER_MODE_MANUAL
);
526 *counter_id
= counter
->id
;
528 rdma_restrack_put(&qp
->res
);
532 rdma_restrack_put(&qp
->res
);
537 * rdma_counter_unbind_qpn() - Unbind QP @qp_num from a counter
539 int rdma_counter_unbind_qpn(struct ib_device
*dev
, u8 port
,
540 u32 qp_num
, u32 counter_id
)
542 struct rdma_port_counter
*port_counter
;
546 if (!rdma_is_port_valid(dev
, port
))
549 qp
= rdma_counter_get_qp(dev
, qp_num
);
553 if (rdma_is_port_valid(dev
, qp
->port
) && (qp
->port
!= port
)) {
558 port_counter
= &dev
->port_data
[port
].port_counter
;
559 if (!qp
->counter
|| qp
->counter
->id
!= counter_id
||
560 port_counter
->mode
.mode
!= RDMA_COUNTER_MODE_MANUAL
) {
565 ret
= rdma_counter_unbind_qp(qp
, false);
568 rdma_restrack_put(&qp
->res
);
572 int rdma_counter_get_mode(struct ib_device
*dev
, u8 port
,
573 enum rdma_nl_counter_mode
*mode
,
574 enum rdma_nl_counter_mask
*mask
)
576 struct rdma_port_counter
*port_counter
;
578 port_counter
= &dev
->port_data
[port
].port_counter
;
579 *mode
= port_counter
->mode
.mode
;
580 *mask
= port_counter
->mode
.mask
;
585 void rdma_counter_init(struct ib_device
*dev
)
587 struct rdma_port_counter
*port_counter
;
593 rdma_for_each_port(dev
, port
) {
594 port_counter
= &dev
->port_data
[port
].port_counter
;
595 port_counter
->mode
.mode
= RDMA_COUNTER_MODE_NONE
;
596 mutex_init(&port_counter
->lock
);
598 if (!dev
->ops
.alloc_hw_stats
)
601 port_counter
->hstats
= dev
->ops
.alloc_hw_stats(dev
, port
);
602 if (!port_counter
->hstats
)
609 for (i
= port
; i
>= rdma_start_port(dev
); i
--) {
610 port_counter
= &dev
->port_data
[port
].port_counter
;
611 kfree(port_counter
->hstats
);
612 port_counter
->hstats
= NULL
;
613 mutex_destroy(&port_counter
->lock
);
617 void rdma_counter_release(struct ib_device
*dev
)
619 struct rdma_port_counter
*port_counter
;
622 rdma_for_each_port(dev
, port
) {
623 port_counter
= &dev
->port_data
[port
].port_counter
;
624 kfree(port_counter
->hstats
);
625 mutex_destroy(&port_counter
->lock
);