xref: /linux/drivers/infiniband/core/uverbs_flow.c (revision 01414b70cb6f7a5911b65de0cc97225061f60a59)
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 #include "uverbs.h"
3 
flow_resources_alloc(size_t num_specs)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->collection);
30 	kfree(resources->counters);
31 	kfree(resources);
32 
33 	return NULL;
34 }
35 EXPORT_SYMBOL(flow_resources_alloc);
36 
ib_uverbs_flow_resources_free(struct ib_uflow_resources * uflow_res)37 void ib_uverbs_flow_resources_free(struct ib_uflow_resources *uflow_res)
38 {
39 	unsigned int i;
40 
41 	if (!uflow_res)
42 		return;
43 
44 	for (i = 0; i < uflow_res->collection_num; i++)
45 		atomic_dec(&uflow_res->collection[i]->usecnt);
46 
47 	for (i = 0; i < uflow_res->counters_num; i++)
48 		atomic_dec(&uflow_res->counters[i]->usecnt);
49 
50 	kfree(uflow_res->collection);
51 	kfree(uflow_res->counters);
52 	kfree(uflow_res);
53 }
54 EXPORT_SYMBOL(ib_uverbs_flow_resources_free);
55 
flow_resources_add(struct ib_uflow_resources * uflow_res,enum ib_flow_spec_type type,void * ibobj)56 void flow_resources_add(struct ib_uflow_resources *uflow_res,
57 			enum ib_flow_spec_type type,
58 			void *ibobj)
59 {
60 	WARN_ON(uflow_res->num >= uflow_res->max);
61 
62 	switch (type) {
63 	case IB_FLOW_SPEC_ACTION_HANDLE:
64 		atomic_inc(&((struct ib_flow_action *)ibobj)->usecnt);
65 		uflow_res->collection[uflow_res->collection_num++] =
66 			(struct ib_flow_action *)ibobj;
67 		break;
68 	case IB_FLOW_SPEC_ACTION_COUNT:
69 		atomic_inc(&((struct ib_counters *)ibobj)->usecnt);
70 		uflow_res->counters[uflow_res->counters_num++] =
71 			(struct ib_counters *)ibobj;
72 		break;
73 	default:
74 		WARN_ON(1);
75 	}
76 
77 	uflow_res->num++;
78 }
79 EXPORT_SYMBOL(flow_resources_add);
80