xref: /linux/drivers/infiniband/core/uverbs_flow.c (revision 9611c0ce215a66770ccbe5c126bf57ba8c31bcad)
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 #include "uverbs.h"
3 
4 struct ib_uflow_resources *flow_resources_alloc(size_t num_specs)
5 {
6 	struct ib_uflow_resources *resources;
7 
8 	resources = kzalloc_obj(*resources);
9 
10 	if (!resources)
11 		return NULL;
12 
13 	if (!num_specs)
14 		goto out;
15 
16 	resources->counters =
17 		kzalloc_objs(*resources->counters, num_specs);
18 	resources->collection =
19 		kzalloc_objs(*resources->collection, num_specs);
20 
21 	if (!resources->counters || !resources->collection)
22 		goto err;
23 
24 out:
25 	resources->max = num_specs;
26 	return resources;
27 
28 err:
29 	kfree(resources->counters);
30 	kfree(resources);
31 
32 	return NULL;
33 }
34 EXPORT_SYMBOL(flow_resources_alloc);
35 
36 void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res)
37 {
38 	unsigned int i;
39 
40 	if (!uflow_res)
41 		return;
42 
43 	for (i = 0; i < uflow_res->collection_num; i++)
44 		atomic_dec(&uflow_res->collection[i]->usecnt);
45 
46 	for (i = 0; i < uflow_res->counters_num; i++)
47 		atomic_dec(&uflow_res->counters[i]->usecnt);
48 
49 	kfree(uflow_res->collection);
50 	kfree(uflow_res->counters);
51 	kfree(uflow_res);
52 }
53 EXPORT_SYMBOL(ib_uverbs_flow_resources_free);
54 
55 void flow_resources_add(struct ib_uflow_resources *uflow_res,
56 			enum ib_flow_spec_type type,
57 			void *ibobj)
58 {
59 	WARN_ON(uflow_res->num >= uflow_res->max);
60 
61 	switch (type) {
62 	case IB_FLOW_SPEC_ACTION_HANDLE:
63 		atomic_inc(&((struct ib_flow_action *)ibobj)->usecnt);
64 		uflow_res->collection[uflow_res->collection_num++] =
65 			(struct ib_flow_action *)ibobj;
66 		break;
67 	case IB_FLOW_SPEC_ACTION_COUNT:
68 		atomic_inc(&((struct ib_counters *)ibobj)->usecnt);
69 		uflow_res->counters[uflow_res->counters_num++] =
70 			(struct ib_counters *)ibobj;
71 		break;
72 	default:
73 		WARN_ON(1);
74 	}
75 
76 	uflow_res->num++;
77 }
78 EXPORT_SYMBOL(flow_resources_add);
79