Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2/*
  3 * Copyright (c) 2019 Mellanox Technologies. All rights reserved.
  4 */
  5#include <rdma/ib_verbs.h>
  6#include <rdma/rdma_counter.h>
  7
  8#include "core_priv.h"
  9#include "restrack.h"
 10
 11#define ALL_AUTO_MODE_MASKS (RDMA_COUNTER_MASK_QP_TYPE | RDMA_COUNTER_MASK_PID)
 12
 13static int __counter_set_mode(struct rdma_port_counter *port_counter,
 14			      enum rdma_nl_counter_mode new_mode,
 15			      enum rdma_nl_counter_mask new_mask)
 16{
 17	if (new_mode == RDMA_COUNTER_MODE_AUTO) {
 18		if (new_mask & (~ALL_AUTO_MODE_MASKS))
 19			return -EINVAL;
 20		if (port_counter->num_counters)
 21			return -EBUSY;
 22	}
 23
 24	port_counter->mode.mode = new_mode;
 25	port_counter->mode.mask = new_mask;
 26	return 0;
 27}
 28
 29/*
 30 * rdma_counter_set_auto_mode() - Turn on/off per-port auto mode
 31 *
 32 * @dev: Device to operate
 33 * @port: Port to use
 34 * @mask: Mask to configure
 35 * @extack: Message to the user
 36 *
 37 * Return 0 on success. If counter mode wasn't changed then it is considered
 38 * as success as well.
 39 * Return -EBUSY when changing to auto mode while there are bounded counters.
 40 *
 41 */
 42int rdma_counter_set_auto_mode(struct ib_device *dev, u32 port,
 43			       enum rdma_nl_counter_mask mask,
 44			       struct netlink_ext_ack *extack)
 45{
 46	struct rdma_port_counter *port_counter;
 47	enum rdma_nl_counter_mode mode;
 48	int ret;
 49
 50	port_counter = &dev->port_data[port].port_counter;
 51	if (!port_counter->hstats)
 52		return -EOPNOTSUPP;
 53
 54	mutex_lock(&port_counter->lock);
 55	if (mask)
 56		mode = RDMA_COUNTER_MODE_AUTO;
 57	else
 58		mode = (port_counter->num_counters) ? RDMA_COUNTER_MODE_MANUAL :
 59						      RDMA_COUNTER_MODE_NONE;
 60
 61	if (port_counter->mode.mode == mode &&
 62	    port_counter->mode.mask == mask) {
 63		ret = 0;
 64		goto out;
 65	}
 66
 67	ret = __counter_set_mode(port_counter, mode, mask);
 
 
 
 
 
 
 68
 69out:
 70	mutex_unlock(&port_counter->lock);
 71	if (ret == -EBUSY)
 72		NL_SET_ERR_MSG(
 73			extack,
 74			"Modifying auto mode is not allowed when there is a bound QP");
 75	return ret;
 76}
 77
 78static void auto_mode_init_counter(struct rdma_counter *counter,
 79				   const struct ib_qp *qp,
 80				   enum rdma_nl_counter_mask new_mask)
 81{
 82	struct auto_mode_param *param = &counter->mode.param;
 83
 84	counter->mode.mode = RDMA_COUNTER_MODE_AUTO;
 85	counter->mode.mask = new_mask;
 86
 87	if (new_mask & RDMA_COUNTER_MASK_QP_TYPE)
 88		param->qp_type = qp->qp_type;
 89}
 90
 91static int __rdma_counter_bind_qp(struct rdma_counter *counter,
 92				  struct ib_qp *qp)
 93{
 94	int ret;
 95
 96	if (qp->counter)
 97		return -EINVAL;
 98
 99	if (!qp->device->ops.counter_bind_qp)
100		return -EOPNOTSUPP;
101
102	mutex_lock(&counter->lock);
103	ret = qp->device->ops.counter_bind_qp(counter, qp);
104	mutex_unlock(&counter->lock);
105
106	return ret;
107}
108
109int 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);
136out:
137	mutex_unlock(&stats->lock);
138	return ret;
139}
140
141static struct rdma_counter *alloc_and_bind(struct ib_device *dev, u32 port,
142					   struct ib_qp *qp,
143					   enum rdma_nl_counter_mode mode)
144{
145	struct rdma_port_counter *port_counter;
146	struct rdma_counter *counter;
147	int ret;
148
149	if (!dev->ops.counter_dealloc || !dev->ops.counter_alloc_stats)
150		return NULL;
151
152	counter = kzalloc(sizeof(*counter), GFP_KERNEL);
153	if (!counter)
154		return NULL;
155
156	counter->device    = dev;
157	counter->port      = port;
158
159	rdma_restrack_new(&counter->res, RDMA_RESTRACK_COUNTER);
160	counter->stats = dev->ops.counter_alloc_stats(counter);
161	if (!counter->stats)
162		goto err_stats;
163
164	port_counter = &dev->port_data[port].port_counter;
165	mutex_lock(&port_counter->lock);
166	switch (mode) {
167	case RDMA_COUNTER_MODE_MANUAL:
168		ret = __counter_set_mode(port_counter, RDMA_COUNTER_MODE_MANUAL,
169					 0);
170		if (ret) {
171			mutex_unlock(&port_counter->lock);
172			goto err_mode;
173		}
174		break;
175	case RDMA_COUNTER_MODE_AUTO:
176		auto_mode_init_counter(counter, qp, port_counter->mode.mask);
177		break;
178	default:
179		ret = -EOPNOTSUPP;
180		mutex_unlock(&port_counter->lock);
181		goto err_mode;
182	}
183
184	port_counter->num_counters++;
185	mutex_unlock(&port_counter->lock);
186
187	counter->mode.mode = mode;
188	kref_init(&counter->kref);
189	mutex_init(&counter->lock);
190
191	ret = __rdma_counter_bind_qp(counter, qp);
192	if (ret)
193		goto err_mode;
194
195	rdma_restrack_parent_name(&counter->res, &qp->res);
196	rdma_restrack_add(&counter->res);
197	return counter;
198
199err_mode:
200	rdma_free_hw_stats_struct(counter->stats);
 
201err_stats:
202	rdma_restrack_put(&counter->res);
203	kfree(counter);
204	return NULL;
205}
206
207static void rdma_counter_free(struct rdma_counter *counter)
208{
209	struct rdma_port_counter *port_counter;
210
211	port_counter = &counter->device->port_data[counter->port].port_counter;
212	mutex_lock(&port_counter->lock);
213	port_counter->num_counters--;
214	if (!port_counter->num_counters &&
215	    (port_counter->mode.mode == RDMA_COUNTER_MODE_MANUAL))
216		__counter_set_mode(port_counter, RDMA_COUNTER_MODE_NONE, 0);
 
217
218	mutex_unlock(&port_counter->lock);
219
220	rdma_restrack_del(&counter->res);
221	rdma_free_hw_stats_struct(counter->stats);
222	kfree(counter);
223}
224
 
 
 
 
 
 
 
 
 
 
 
 
 
225static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter,
226			    enum rdma_nl_counter_mask auto_mask)
227{
228	struct auto_mode_param *param = &counter->mode.param;
229	bool match = true;
230
 
 
 
 
 
 
 
231	if (auto_mask & RDMA_COUNTER_MASK_QP_TYPE)
232		match &= (param->qp_type == qp->qp_type);
233
234	if (auto_mask & RDMA_COUNTER_MASK_PID)
235		match &= (task_pid_nr(counter->res.task) ==
236			  task_pid_nr(qp->res.task));
237
238	return match;
239}
240
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241static int __rdma_counter_unbind_qp(struct ib_qp *qp)
242{
243	struct rdma_counter *counter = qp->counter;
244	int ret;
245
246	if (!qp->device->ops.counter_unbind_qp)
247		return -EOPNOTSUPP;
248
249	mutex_lock(&counter->lock);
250	ret = qp->device->ops.counter_unbind_qp(qp);
251	mutex_unlock(&counter->lock);
252
253	return ret;
254}
255
256static void counter_history_stat_update(struct rdma_counter *counter)
257{
258	struct ib_device *dev = counter->device;
259	struct rdma_port_counter *port_counter;
260	int i;
261
262	port_counter = &dev->port_data[counter->port].port_counter;
263	if (!port_counter->hstats)
264		return;
265
266	rdma_counter_query_stats(counter);
267
268	for (i = 0; i < counter->stats->num_counters; i++)
269		port_counter->hstats->value[i] += counter->stats->value[i];
270}
271
272/*
273 * rdma_get_counter_auto_mode - Find the counter that @qp should be bound
274 *     with in auto mode
275 *
276 * Return: The counter (with ref-count increased) if found
277 */
278static struct rdma_counter *rdma_get_counter_auto_mode(struct ib_qp *qp,
279						       u32 port)
280{
281	struct rdma_port_counter *port_counter;
282	struct rdma_counter *counter = NULL;
283	struct ib_device *dev = qp->device;
284	struct rdma_restrack_entry *res;
285	struct rdma_restrack_root *rt;
286	unsigned long id = 0;
287
288	port_counter = &dev->port_data[port].port_counter;
289	rt = &dev->res[RDMA_RESTRACK_COUNTER];
290	xa_lock(&rt->xa);
291	xa_for_each(&rt->xa, id, res) {
 
 
 
292		counter = container_of(res, struct rdma_counter, res);
293		if ((counter->device != qp->device) || (counter->port != port))
294			goto next;
295
296		if (auto_mode_match(qp, counter, port_counter->mode.mask))
297			break;
298next:
299		counter = NULL;
300	}
301
302	if (counter && !kref_get_unless_zero(&counter->kref))
303		counter = NULL;
304
305	xa_unlock(&rt->xa);
306	return counter;
307}
308
 
 
 
 
 
 
 
 
 
 
 
 
309static void counter_release(struct kref *kref)
310{
311	struct rdma_counter *counter;
312
313	counter = container_of(kref, struct rdma_counter, kref);
314	counter_history_stat_update(counter);
315	counter->device->ops.counter_dealloc(counter);
316	rdma_counter_free(counter);
317}
318
319/*
320 * rdma_counter_bind_qp_auto - Check and bind the QP to a counter base on
321 *   the auto-mode rule
322 */
323int rdma_counter_bind_qp_auto(struct ib_qp *qp, u32 port)
324{
325	struct rdma_port_counter *port_counter;
326	struct ib_device *dev = qp->device;
327	struct rdma_counter *counter;
328	int ret;
329
330	if (!rdma_restrack_is_tracked(&qp->res) || rdma_is_kernel_res(&qp->res))
331		return 0;
332
333	if (!rdma_is_port_valid(dev, port))
334		return -EINVAL;
335
336	port_counter = &dev->port_data[port].port_counter;
337	if (port_counter->mode.mode != RDMA_COUNTER_MODE_AUTO)
338		return 0;
339
340	counter = rdma_get_counter_auto_mode(qp, port);
341	if (counter) {
342		ret = __rdma_counter_bind_qp(counter, qp);
343		if (ret) {
344			kref_put(&counter->kref, counter_release);
345			return ret;
346		}
347	} else {
348		counter = alloc_and_bind(dev, port, qp, RDMA_COUNTER_MODE_AUTO);
349		if (!counter)
350			return -ENOMEM;
 
 
 
 
 
 
 
 
 
 
351	}
352
353	return 0;
354}
355
356/*
357 * rdma_counter_unbind_qp - Unbind a qp from a counter
358 * @force:
359 *   true - Decrease the counter ref-count anyway (e.g., qp destroy)
360 */
361int rdma_counter_unbind_qp(struct ib_qp *qp, bool force)
362{
363	struct rdma_counter *counter = qp->counter;
364	int ret;
365
366	if (!counter)
367		return -EINVAL;
368
369	ret = __rdma_counter_unbind_qp(qp);
370	if (ret && !force)
371		return ret;
372
373	kref_put(&counter->kref, counter_release);
374	return 0;
375}
376
377int rdma_counter_query_stats(struct rdma_counter *counter)
378{
379	struct ib_device *dev = counter->device;
380	int ret;
381
382	if (!dev->ops.counter_update_stats)
383		return -EINVAL;
384
385	mutex_lock(&counter->lock);
386	ret = dev->ops.counter_update_stats(counter);
387	mutex_unlock(&counter->lock);
388
389	return ret;
390}
391
392static u64 get_running_counters_hwstat_sum(struct ib_device *dev,
393					   u32 port, u32 index)
394{
395	struct rdma_restrack_entry *res;
396	struct rdma_restrack_root *rt;
397	struct rdma_counter *counter;
398	unsigned long id = 0;
399	u64 sum = 0;
400
401	rt = &dev->res[RDMA_RESTRACK_COUNTER];
402	xa_lock(&rt->xa);
403	xa_for_each(&rt->xa, id, res) {
404		if (!rdma_restrack_get(res))
405			continue;
406
407		xa_unlock(&rt->xa);
408
409		counter = container_of(res, struct rdma_counter, res);
410		if ((counter->device != dev) || (counter->port != port) ||
411		    rdma_counter_query_stats(counter))
412			goto next;
413
414		sum += counter->stats->value[index];
415
416next:
417		xa_lock(&rt->xa);
418		rdma_restrack_put(res);
419	}
420
421	xa_unlock(&rt->xa);
422	return sum;
423}
424
425/*
426 * rdma_counter_get_hwstat_value() - Get the sum value of all counters on a
427 *   specific port, including the running ones and history data
428 */
429u64 rdma_counter_get_hwstat_value(struct ib_device *dev, u32 port, u32 index)
430{
431	struct rdma_port_counter *port_counter;
432	u64 sum;
433
434	port_counter = &dev->port_data[port].port_counter;
435	if (!port_counter->hstats)
436		return 0;
437
438	sum = get_running_counters_hwstat_sum(dev, port, index);
439	sum += port_counter->hstats->value[index];
440
441	return sum;
442}
443
444static struct ib_qp *rdma_counter_get_qp(struct ib_device *dev, u32 qp_num)
445{
446	struct rdma_restrack_entry *res = NULL;
447	struct ib_qp *qp = NULL;
448
449	res = rdma_restrack_get_byid(dev, RDMA_RESTRACK_QP, qp_num);
450	if (IS_ERR(res))
451		return NULL;
452
 
 
 
453	qp = container_of(res, struct ib_qp, res);
454	if (qp->qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW))
455		goto err;
456
457	return qp;
458
459err:
460	rdma_restrack_put(res);
461	return NULL;
462}
463
 
 
 
 
 
 
 
 
 
464static struct rdma_counter *rdma_get_counter_by_id(struct ib_device *dev,
465						   u32 counter_id)
466{
467	struct rdma_restrack_entry *res;
468	struct rdma_counter *counter;
469
470	res = rdma_restrack_get_byid(dev, RDMA_RESTRACK_COUNTER, counter_id);
471	if (IS_ERR(res))
472		return NULL;
473
 
 
 
 
 
474	counter = container_of(res, struct rdma_counter, res);
475	kref_get(&counter->kref);
476	rdma_restrack_put(res);
477
478	return counter;
479}
480
481/*
482 * rdma_counter_bind_qpn() - Bind QP @qp_num to counter @counter_id
483 */
484int rdma_counter_bind_qpn(struct ib_device *dev, u32 port,
485			  u32 qp_num, u32 counter_id)
486{
487	struct rdma_port_counter *port_counter;
488	struct rdma_counter *counter;
489	struct ib_qp *qp;
490	int ret;
491
492	port_counter = &dev->port_data[port].port_counter;
493	if (port_counter->mode.mode == RDMA_COUNTER_MODE_AUTO)
494		return -EINVAL;
495
496	qp = rdma_counter_get_qp(dev, qp_num);
497	if (!qp)
498		return -ENOENT;
499
500	counter = rdma_get_counter_by_id(dev, counter_id);
501	if (!counter) {
502		ret = -ENOENT;
503		goto err;
504	}
505
506	if (rdma_is_kernel_res(&counter->res) != rdma_is_kernel_res(&qp->res)) {
507		ret = -EINVAL;
508		goto err_task;
509	}
510
511	if ((counter->device != qp->device) || (counter->port != qp->port)) {
512		ret = -EINVAL;
513		goto err_task;
514	}
515
516	ret = __rdma_counter_bind_qp(counter, qp);
517	if (ret)
518		goto err_task;
519
520	rdma_restrack_put(&qp->res);
521	return 0;
522
523err_task:
524	kref_put(&counter->kref, counter_release);
525err:
526	rdma_restrack_put(&qp->res);
527	return ret;
528}
529
530/*
531 * rdma_counter_bind_qpn_alloc() - Alloc a counter and bind QP @qp_num to it
532 *   The id of new counter is returned in @counter_id
533 */
534int rdma_counter_bind_qpn_alloc(struct ib_device *dev, u32 port,
535				u32 qp_num, u32 *counter_id)
536{
537	struct rdma_port_counter *port_counter;
538	struct rdma_counter *counter;
539	struct ib_qp *qp;
540	int ret;
541
542	if (!rdma_is_port_valid(dev, port))
543		return -EINVAL;
544
545	port_counter = &dev->port_data[port].port_counter;
546	if (!port_counter->hstats)
547		return -EOPNOTSUPP;
548
549	if (port_counter->mode.mode == RDMA_COUNTER_MODE_AUTO)
550		return -EINVAL;
551
552	qp = rdma_counter_get_qp(dev, qp_num);
553	if (!qp)
554		return -ENOENT;
555
556	if (rdma_is_port_valid(dev, qp->port) && (qp->port != port)) {
557		ret = -EINVAL;
558		goto err;
559	}
560
561	counter = alloc_and_bind(dev, port, qp, RDMA_COUNTER_MODE_MANUAL);
562	if (!counter) {
563		ret = -ENOMEM;
564		goto err;
565	}
566
 
 
 
 
567	if (counter_id)
568		*counter_id = counter->id;
569
 
 
570	rdma_restrack_put(&qp->res);
571	return 0;
572
 
 
573err:
574	rdma_restrack_put(&qp->res);
575	return ret;
576}
577
578/*
579 * rdma_counter_unbind_qpn() - Unbind QP @qp_num from a counter
580 */
581int rdma_counter_unbind_qpn(struct ib_device *dev, u32 port,
582			    u32 qp_num, u32 counter_id)
583{
584	struct rdma_port_counter *port_counter;
585	struct ib_qp *qp;
586	int ret;
587
588	if (!rdma_is_port_valid(dev, port))
589		return -EINVAL;
590
591	qp = rdma_counter_get_qp(dev, qp_num);
592	if (!qp)
593		return -ENOENT;
594
595	if (rdma_is_port_valid(dev, qp->port) && (qp->port != port)) {
596		ret = -EINVAL;
597		goto out;
598	}
599
600	port_counter = &dev->port_data[port].port_counter;
601	if (!qp->counter || qp->counter->id != counter_id ||
602	    port_counter->mode.mode != RDMA_COUNTER_MODE_MANUAL) {
603		ret = -EINVAL;
604		goto out;
605	}
606
607	ret = rdma_counter_unbind_qp(qp, false);
608
609out:
610	rdma_restrack_put(&qp->res);
611	return ret;
612}
613
614int rdma_counter_get_mode(struct ib_device *dev, u32 port,
615			  enum rdma_nl_counter_mode *mode,
616			  enum rdma_nl_counter_mask *mask)
617{
618	struct rdma_port_counter *port_counter;
619
620	port_counter = &dev->port_data[port].port_counter;
621	*mode = port_counter->mode.mode;
622	*mask = port_counter->mode.mask;
623
624	return 0;
625}
626
627void rdma_counter_init(struct ib_device *dev)
628{
629	struct rdma_port_counter *port_counter;
630	u32 port, i;
631
632	if (!dev->port_data)
633		return;
634
635	rdma_for_each_port(dev, port) {
636		port_counter = &dev->port_data[port].port_counter;
637		port_counter->mode.mode = RDMA_COUNTER_MODE_NONE;
638		mutex_init(&port_counter->lock);
639
640		if (!dev->ops.alloc_hw_port_stats)
641			continue;
642
643		port_counter->hstats = dev->ops.alloc_hw_port_stats(dev, port);
644		if (!port_counter->hstats)
645			goto fail;
646	}
647
648	return;
649
650fail:
651	for (i = port; i >= rdma_start_port(dev); i--) {
652		port_counter = &dev->port_data[port].port_counter;
653		rdma_free_hw_stats_struct(port_counter->hstats);
654		port_counter->hstats = NULL;
655		mutex_destroy(&port_counter->lock);
656	}
657}
658
659void rdma_counter_release(struct ib_device *dev)
660{
661	struct rdma_port_counter *port_counter;
662	u32 port;
663
664	rdma_for_each_port(dev, port) {
665		port_counter = &dev->port_data[port].port_counter;
666		rdma_free_hw_stats_struct(port_counter->hstats);
667		mutex_destroy(&port_counter->lock);
668	}
669}
v5.4
  1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2/*
  3 * Copyright (c) 2019 Mellanox Technologies. All rights reserved.
  4 */
  5#include <rdma/ib_verbs.h>
  6#include <rdma/rdma_counter.h>
  7
  8#include "core_priv.h"
  9#include "restrack.h"
 10
 11#define ALL_AUTO_MODE_MASKS (RDMA_COUNTER_MASK_QP_TYPE)
 12
 13static 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)
 16{
 17	if ((new_mode == RDMA_COUNTER_MODE_AUTO) &&
 18	    ((new_mask & (~ALL_AUTO_MODE_MASKS)) ||
 19	     (curr->mode != RDMA_COUNTER_MODE_NONE)))
 20		return -EINVAL;
 
 
 21
 22	curr->mode = new_mode;
 23	curr->mask = new_mask;
 24	return 0;
 25}
 26
 27/**
 28 * rdma_counter_set_auto_mode() - Turn on/off per-port auto mode
 29 *
 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.
 
 
 
 
 
 
 33 */
 34int rdma_counter_set_auto_mode(struct ib_device *dev, u8 port,
 35			       bool on, enum rdma_nl_counter_mask mask)
 
 36{
 37	struct rdma_port_counter *port_counter;
 
 38	int ret;
 39
 40	port_counter = &dev->port_data[port].port_counter;
 41	if (!port_counter->hstats)
 42		return -EOPNOTSUPP;
 43
 44	mutex_lock(&port_counter->lock);
 45	if (on) {
 46		ret = __counter_set_mode(&port_counter->mode,
 47					 RDMA_COUNTER_MODE_AUTO, mask);
 48	} else {
 49		if (port_counter->mode.mode != RDMA_COUNTER_MODE_AUTO) {
 50			ret = -EINVAL;
 51			goto out;
 52		}
 
 
 
 53
 54		if (port_counter->num_counters)
 55			ret = __counter_set_mode(&port_counter->mode,
 56						 RDMA_COUNTER_MODE_MANUAL, 0);
 57		else
 58			ret = __counter_set_mode(&port_counter->mode,
 59						 RDMA_COUNTER_MODE_NONE, 0);
 60	}
 61
 62out:
 63	mutex_unlock(&port_counter->lock);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 64	return ret;
 65}
 66
 67static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port,
 68					       enum rdma_nl_counter_mode mode)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 69{
 70	struct rdma_port_counter *port_counter;
 71	struct rdma_counter *counter;
 72	int ret;
 73
 74	if (!dev->ops.counter_dealloc || !dev->ops.counter_alloc_stats)
 75		return NULL;
 76
 77	counter = kzalloc(sizeof(*counter), GFP_KERNEL);
 78	if (!counter)
 79		return NULL;
 80
 81	counter->device    = dev;
 82	counter->port      = port;
 83	counter->res.type  = RDMA_RESTRACK_COUNTER;
 84	counter->stats     = dev->ops.counter_alloc_stats(counter);
 
 85	if (!counter->stats)
 86		goto err_stats;
 87
 88	port_counter = &dev->port_data[port].port_counter;
 89	mutex_lock(&port_counter->lock);
 90	if (mode == RDMA_COUNTER_MODE_MANUAL) {
 91		ret = __counter_set_mode(&port_counter->mode,
 92					 RDMA_COUNTER_MODE_MANUAL, 0);
 93		if (ret)
 
 
 94			goto err_mode;
 
 
 
 
 
 
 
 
 
 95	}
 96
 97	port_counter->num_counters++;
 98	mutex_unlock(&port_counter->lock);
 99
100	counter->mode.mode = mode;
101	kref_init(&counter->kref);
102	mutex_init(&counter->lock);
103
 
 
 
 
 
 
104	return counter;
105
106err_mode:
107	mutex_unlock(&port_counter->lock);
108	kfree(counter->stats);
109err_stats:
 
110	kfree(counter);
111	return NULL;
112}
113
114static void rdma_counter_free(struct rdma_counter *counter)
115{
116	struct rdma_port_counter *port_counter;
117
118	port_counter = &counter->device->port_data[counter->port].port_counter;
119	mutex_lock(&port_counter->lock);
120	port_counter->num_counters--;
121	if (!port_counter->num_counters &&
122	    (port_counter->mode.mode == RDMA_COUNTER_MODE_MANUAL))
123		__counter_set_mode(&port_counter->mode, RDMA_COUNTER_MODE_NONE,
124				   0);
125
126	mutex_unlock(&port_counter->lock);
127
128	rdma_restrack_del(&counter->res);
129	kfree(counter->stats);
130	kfree(counter);
131}
132
133static void auto_mode_init_counter(struct rdma_counter *counter,
134				   const struct ib_qp *qp,
135				   enum rdma_nl_counter_mask new_mask)
136{
137	struct auto_mode_param *param = &counter->mode.param;
138
139	counter->mode.mode = RDMA_COUNTER_MODE_AUTO;
140	counter->mode.mask = new_mask;
141
142	if (new_mask & RDMA_COUNTER_MASK_QP_TYPE)
143		param->qp_type = qp->qp_type;
144}
145
146static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter,
147			    enum rdma_nl_counter_mask auto_mask)
148{
149	struct auto_mode_param *param = &counter->mode.param;
150	bool match = true;
151
152	if (!rdma_is_visible_in_pid_ns(&qp->res))
153		return false;
154
155	/* Ensure that counter belongs to the right PID */
156	if (task_pid_nr(counter->res.task) != task_pid_nr(qp->res.task))
157		return false;
158
159	if (auto_mask & RDMA_COUNTER_MASK_QP_TYPE)
160		match &= (param->qp_type == qp->qp_type);
161
 
 
 
 
162	return match;
163}
164
165static int __rdma_counter_bind_qp(struct rdma_counter *counter,
166				  struct ib_qp *qp)
167{
168	int ret;
169
170	if (qp->counter)
171		return -EINVAL;
172
173	if (!qp->device->ops.counter_bind_qp)
174		return -EOPNOTSUPP;
175
176	mutex_lock(&counter->lock);
177	ret = qp->device->ops.counter_bind_qp(counter, qp);
178	mutex_unlock(&counter->lock);
179
180	return ret;
181}
182
183static int __rdma_counter_unbind_qp(struct ib_qp *qp)
184{
185	struct rdma_counter *counter = qp->counter;
186	int ret;
187
188	if (!qp->device->ops.counter_unbind_qp)
189		return -EOPNOTSUPP;
190
191	mutex_lock(&counter->lock);
192	ret = qp->device->ops.counter_unbind_qp(qp);
193	mutex_unlock(&counter->lock);
194
195	return ret;
196}
197
198static void counter_history_stat_update(const struct rdma_counter *counter)
199{
200	struct ib_device *dev = counter->device;
201	struct rdma_port_counter *port_counter;
202	int i;
203
204	port_counter = &dev->port_data[counter->port].port_counter;
205	if (!port_counter->hstats)
206		return;
207
 
 
208	for (i = 0; i < counter->stats->num_counters; i++)
209		port_counter->hstats->value[i] += counter->stats->value[i];
210}
211
212/**
213 * rdma_get_counter_auto_mode - Find the counter that @qp should be bound
214 *     with in auto mode
215 *
216 * Return: The counter (with ref-count increased) if found
217 */
218static struct rdma_counter *rdma_get_counter_auto_mode(struct ib_qp *qp,
219						       u8 port)
220{
221	struct rdma_port_counter *port_counter;
222	struct rdma_counter *counter = NULL;
223	struct ib_device *dev = qp->device;
224	struct rdma_restrack_entry *res;
225	struct rdma_restrack_root *rt;
226	unsigned long id = 0;
227
228	port_counter = &dev->port_data[port].port_counter;
229	rt = &dev->res[RDMA_RESTRACK_COUNTER];
230	xa_lock(&rt->xa);
231	xa_for_each(&rt->xa, id, res) {
232		if (!rdma_is_visible_in_pid_ns(res))
233			continue;
234
235		counter = container_of(res, struct rdma_counter, res);
236		if ((counter->device != qp->device) || (counter->port != port))
237			goto next;
238
239		if (auto_mode_match(qp, counter, port_counter->mode.mask))
240			break;
241next:
242		counter = NULL;
243	}
244
245	if (counter && !kref_get_unless_zero(&counter->kref))
246		counter = NULL;
247
248	xa_unlock(&rt->xa);
249	return counter;
250}
251
252static void rdma_counter_res_add(struct rdma_counter *counter,
253				 struct ib_qp *qp)
254{
255	if (rdma_is_kernel_res(&qp->res)) {
256		rdma_restrack_set_task(&counter->res, qp->res.kern_name);
257		rdma_restrack_kadd(&counter->res);
258	} else {
259		rdma_restrack_attach_task(&counter->res, qp->res.task);
260		rdma_restrack_uadd(&counter->res);
261	}
262}
263
264static void counter_release(struct kref *kref)
265{
266	struct rdma_counter *counter;
267
268	counter = container_of(kref, struct rdma_counter, kref);
269	counter_history_stat_update(counter);
270	counter->device->ops.counter_dealloc(counter);
271	rdma_counter_free(counter);
272}
273
274/**
275 * rdma_counter_bind_qp_auto - Check and bind the QP to a counter base on
276 *   the auto-mode rule
277 */
278int rdma_counter_bind_qp_auto(struct ib_qp *qp, u8 port)
279{
280	struct rdma_port_counter *port_counter;
281	struct ib_device *dev = qp->device;
282	struct rdma_counter *counter;
283	int ret;
284
 
 
 
285	if (!rdma_is_port_valid(dev, port))
286		return -EINVAL;
287
288	port_counter = &dev->port_data[port].port_counter;
289	if (port_counter->mode.mode != RDMA_COUNTER_MODE_AUTO)
290		return 0;
291
292	counter = rdma_get_counter_auto_mode(qp, port);
293	if (counter) {
294		ret = __rdma_counter_bind_qp(counter, qp);
295		if (ret) {
296			kref_put(&counter->kref, counter_release);
297			return ret;
298		}
299	} else {
300		counter = rdma_counter_alloc(dev, port, RDMA_COUNTER_MODE_AUTO);
301		if (!counter)
302			return -ENOMEM;
303
304		auto_mode_init_counter(counter, qp, port_counter->mode.mask);
305
306		ret = __rdma_counter_bind_qp(counter, qp);
307		if (ret) {
308			rdma_counter_free(counter);
309			return ret;
310		}
311
312		rdma_counter_res_add(counter, qp);
313	}
314
315	return 0;
316}
317
318/**
319 * rdma_counter_unbind_qp - Unbind a qp from a counter
320 * @force:
321 *   true - Decrease the counter ref-count anyway (e.g., qp destroy)
322 */
323int rdma_counter_unbind_qp(struct ib_qp *qp, bool force)
324{
325	struct rdma_counter *counter = qp->counter;
326	int ret;
327
328	if (!counter)
329		return -EINVAL;
330
331	ret = __rdma_counter_unbind_qp(qp);
332	if (ret && !force)
333		return ret;
334
335	kref_put(&counter->kref, counter_release);
336	return 0;
337}
338
339int rdma_counter_query_stats(struct rdma_counter *counter)
340{
341	struct ib_device *dev = counter->device;
342	int ret;
343
344	if (!dev->ops.counter_update_stats)
345		return -EINVAL;
346
347	mutex_lock(&counter->lock);
348	ret = dev->ops.counter_update_stats(counter);
349	mutex_unlock(&counter->lock);
350
351	return ret;
352}
353
354static u64 get_running_counters_hwstat_sum(struct ib_device *dev,
355					   u8 port, u32 index)
356{
357	struct rdma_restrack_entry *res;
358	struct rdma_restrack_root *rt;
359	struct rdma_counter *counter;
360	unsigned long id = 0;
361	u64 sum = 0;
362
363	rt = &dev->res[RDMA_RESTRACK_COUNTER];
364	xa_lock(&rt->xa);
365	xa_for_each(&rt->xa, id, res) {
366		if (!rdma_restrack_get(res))
367			continue;
368
369		xa_unlock(&rt->xa);
370
371		counter = container_of(res, struct rdma_counter, res);
372		if ((counter->device != dev) || (counter->port != port) ||
373		    rdma_counter_query_stats(counter))
374			goto next;
375
376		sum += counter->stats->value[index];
377
378next:
379		xa_lock(&rt->xa);
380		rdma_restrack_put(res);
381	}
382
383	xa_unlock(&rt->xa);
384	return sum;
385}
386
387/**
388 * rdma_counter_get_hwstat_value() - Get the sum value of all counters on a
389 *   specific port, including the running ones and history data
390 */
391u64 rdma_counter_get_hwstat_value(struct ib_device *dev, u8 port, u32 index)
392{
393	struct rdma_port_counter *port_counter;
394	u64 sum;
395
396	port_counter = &dev->port_data[port].port_counter;
397	if (!port_counter->hstats)
398		return 0;
399
400	sum = get_running_counters_hwstat_sum(dev, port, index);
401	sum += port_counter->hstats->value[index];
402
403	return sum;
404}
405
406static struct ib_qp *rdma_counter_get_qp(struct ib_device *dev, u32 qp_num)
407{
408	struct rdma_restrack_entry *res = NULL;
409	struct ib_qp *qp = NULL;
410
411	res = rdma_restrack_get_byid(dev, RDMA_RESTRACK_QP, qp_num);
412	if (IS_ERR(res))
413		return NULL;
414
415	if (!rdma_is_visible_in_pid_ns(res))
416		goto err;
417
418	qp = container_of(res, struct ib_qp, res);
419	if (qp->qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW))
420		goto err;
421
422	return qp;
423
424err:
425	rdma_restrack_put(res);
426	return NULL;
427}
428
429static int rdma_counter_bind_qp_manual(struct rdma_counter *counter,
430				       struct ib_qp *qp)
431{
432	if ((counter->device != qp->device) || (counter->port != qp->port))
433		return -EINVAL;
434
435	return __rdma_counter_bind_qp(counter, qp);
436}
437
438static struct rdma_counter *rdma_get_counter_by_id(struct ib_device *dev,
439						   u32 counter_id)
440{
441	struct rdma_restrack_entry *res;
442	struct rdma_counter *counter;
443
444	res = rdma_restrack_get_byid(dev, RDMA_RESTRACK_COUNTER, counter_id);
445	if (IS_ERR(res))
446		return NULL;
447
448	if (!rdma_is_visible_in_pid_ns(res)) {
449		rdma_restrack_put(res);
450		return NULL;
451	}
452
453	counter = container_of(res, struct rdma_counter, res);
454	kref_get(&counter->kref);
455	rdma_restrack_put(res);
456
457	return counter;
458}
459
460/**
461 * rdma_counter_bind_qpn() - Bind QP @qp_num to counter @counter_id
462 */
463int rdma_counter_bind_qpn(struct ib_device *dev, u8 port,
464			  u32 qp_num, u32 counter_id)
465{
 
466	struct rdma_counter *counter;
467	struct ib_qp *qp;
468	int ret;
469
 
 
 
 
470	qp = rdma_counter_get_qp(dev, qp_num);
471	if (!qp)
472		return -ENOENT;
473
474	counter = rdma_get_counter_by_id(dev, counter_id);
475	if (!counter) {
476		ret = -ENOENT;
477		goto err;
478	}
479
480	if (counter->res.task != qp->res.task) {
481		ret = -EINVAL;
482		goto err_task;
483	}
484
485	ret = rdma_counter_bind_qp_manual(counter, qp);
 
 
 
 
 
486	if (ret)
487		goto err_task;
488
489	rdma_restrack_put(&qp->res);
490	return 0;
491
492err_task:
493	kref_put(&counter->kref, counter_release);
494err:
495	rdma_restrack_put(&qp->res);
496	return ret;
497}
498
499/**
500 * rdma_counter_bind_qpn_alloc() - Alloc a counter and bind QP @qp_num to it
501 *   The id of new counter is returned in @counter_id
502 */
503int rdma_counter_bind_qpn_alloc(struct ib_device *dev, u8 port,
504				u32 qp_num, u32 *counter_id)
505{
 
506	struct rdma_counter *counter;
507	struct ib_qp *qp;
508	int ret;
509
510	if (!rdma_is_port_valid(dev, port))
511		return -EINVAL;
512
513	if (!dev->port_data[port].port_counter.hstats)
 
514		return -EOPNOTSUPP;
515
 
 
 
516	qp = rdma_counter_get_qp(dev, qp_num);
517	if (!qp)
518		return -ENOENT;
519
520	if (rdma_is_port_valid(dev, qp->port) && (qp->port != port)) {
521		ret = -EINVAL;
522		goto err;
523	}
524
525	counter = rdma_counter_alloc(dev, port, RDMA_COUNTER_MODE_MANUAL);
526	if (!counter) {
527		ret = -ENOMEM;
528		goto err;
529	}
530
531	ret = rdma_counter_bind_qp_manual(counter, qp);
532	if (ret)
533		goto err_bind;
534
535	if (counter_id)
536		*counter_id = counter->id;
537
538	rdma_counter_res_add(counter, qp);
539
540	rdma_restrack_put(&qp->res);
541	return ret;
542
543err_bind:
544	rdma_counter_free(counter);
545err:
546	rdma_restrack_put(&qp->res);
547	return ret;
548}
549
550/**
551 * rdma_counter_unbind_qpn() - Unbind QP @qp_num from a counter
552 */
553int rdma_counter_unbind_qpn(struct ib_device *dev, u8 port,
554			    u32 qp_num, u32 counter_id)
555{
556	struct rdma_port_counter *port_counter;
557	struct ib_qp *qp;
558	int ret;
559
560	if (!rdma_is_port_valid(dev, port))
561		return -EINVAL;
562
563	qp = rdma_counter_get_qp(dev, qp_num);
564	if (!qp)
565		return -ENOENT;
566
567	if (rdma_is_port_valid(dev, qp->port) && (qp->port != port)) {
568		ret = -EINVAL;
569		goto out;
570	}
571
572	port_counter = &dev->port_data[port].port_counter;
573	if (!qp->counter || qp->counter->id != counter_id ||
574	    port_counter->mode.mode != RDMA_COUNTER_MODE_MANUAL) {
575		ret = -EINVAL;
576		goto out;
577	}
578
579	ret = rdma_counter_unbind_qp(qp, false);
580
581out:
582	rdma_restrack_put(&qp->res);
583	return ret;
584}
585
586int rdma_counter_get_mode(struct ib_device *dev, u8 port,
587			  enum rdma_nl_counter_mode *mode,
588			  enum rdma_nl_counter_mask *mask)
589{
590	struct rdma_port_counter *port_counter;
591
592	port_counter = &dev->port_data[port].port_counter;
593	*mode = port_counter->mode.mode;
594	*mask = port_counter->mode.mask;
595
596	return 0;
597}
598
599void rdma_counter_init(struct ib_device *dev)
600{
601	struct rdma_port_counter *port_counter;
602	u32 port, i;
603
604	if (!dev->port_data)
605		return;
606
607	rdma_for_each_port(dev, port) {
608		port_counter = &dev->port_data[port].port_counter;
609		port_counter->mode.mode = RDMA_COUNTER_MODE_NONE;
610		mutex_init(&port_counter->lock);
611
612		if (!dev->ops.alloc_hw_stats)
613			continue;
614
615		port_counter->hstats = dev->ops.alloc_hw_stats(dev, port);
616		if (!port_counter->hstats)
617			goto fail;
618	}
619
620	return;
621
622fail:
623	for (i = port; i >= rdma_start_port(dev); i--) {
624		port_counter = &dev->port_data[port].port_counter;
625		kfree(port_counter->hstats);
626		port_counter->hstats = NULL;
627		mutex_destroy(&port_counter->lock);
628	}
629}
630
631void rdma_counter_release(struct ib_device *dev)
632{
633	struct rdma_port_counter *port_counter;
634	u32 port;
635
636	rdma_for_each_port(dev, port) {
637		port_counter = &dev->port_data[port].port_counter;
638		kfree(port_counter->hstats);
639		mutex_destroy(&port_counter->lock);
640	}
641}