blob: e10c75a473cea76dbc4fc596c7ee85ef1f7960e6 [file] [log] [blame]
Amir Levy9659e592016-10-27 18:08:27 +03001/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/slab.h>
14#include "ipa_rm_dependency_graph.h"
15#include "ipa_rm_i.h"
16
17static int ipa_rm_dep_get_index(enum ipa_rm_resource_name resource_name)
18{
19 int resource_index = IPA_RM_INDEX_INVALID;
20
21 if (IPA_RM_RESORCE_IS_PROD(resource_name))
22 resource_index = ipa_rm_prod_index(resource_name);
23 else if (IPA_RM_RESORCE_IS_CONS(resource_name))
24 resource_index = ipa_rm_cons_index(resource_name);
25
26 return resource_index;
27}
28
29/**
30 * ipa_rm_dep_graph_create() - creates graph
31 * @dep_graph: [out] created dependency graph
32 *
33 * Returns: dependency graph on success, NULL on failure
34 */
35int ipa_rm_dep_graph_create(struct ipa_rm_dep_graph **dep_graph)
36{
37 int result = 0;
38
39 *dep_graph = kzalloc(sizeof(**dep_graph), GFP_KERNEL);
40 if (!*dep_graph) {
41 IPA_RM_ERR("no mem\n");
42 result = -ENOMEM;
43 goto bail;
44 }
45bail:
46 return result;
47}
48
49/**
50 * ipa_rm_dep_graph_delete() - destroyes the graph
51 * @graph: [in] dependency graph
52 *
53 * Frees all resources.
54 */
55void ipa_rm_dep_graph_delete(struct ipa_rm_dep_graph *graph)
56{
57 int resource_index;
58
59 if (!graph) {
60 IPA_RM_ERR("invalid params\n");
61 return;
62 }
63 for (resource_index = 0;
64 resource_index < IPA_RM_RESOURCE_MAX;
65 resource_index++)
66 kfree(graph->resource_table[resource_index]);
67 memset(graph->resource_table, 0, sizeof(graph->resource_table));
68}
69
70/**
71 * ipa_rm_dep_graph_get_resource() - provides a resource by name
72 * @graph: [in] dependency graph
73 * @name: [in] name of the resource
74 * @resource: [out] resource in case of success
75 *
76 * Returns: 0 on success, negative on failure
77 */
78int ipa_rm_dep_graph_get_resource(
79 struct ipa_rm_dep_graph *graph,
80 enum ipa_rm_resource_name resource_name,
81 struct ipa_rm_resource **resource)
82{
83 int result;
84 int resource_index;
85
86 if (!graph) {
87 result = -EINVAL;
88 goto bail;
89 }
90 resource_index = ipa_rm_dep_get_index(resource_name);
91 if (resource_index == IPA_RM_INDEX_INVALID) {
92 result = -EINVAL;
93 goto bail;
94 }
95 *resource = graph->resource_table[resource_index];
96 if (!*resource) {
97 result = -EINVAL;
98 goto bail;
99 }
100 result = 0;
101bail:
102 return result;
103}
104
105/**
106 * ipa_rm_dep_graph_add() - adds resource to graph
107 * @graph: [in] dependency graph
108 * @resource: [in] resource to add
109 *
110 * Returns: 0 on success, negative on failure
111 */
112int ipa_rm_dep_graph_add(struct ipa_rm_dep_graph *graph,
113 struct ipa_rm_resource *resource)
114{
115 int result = 0;
116 int resource_index;
117
118 if (!graph || !resource) {
119 result = -EINVAL;
120 goto bail;
121 }
122 resource_index = ipa_rm_dep_get_index(resource->name);
123 if (resource_index == IPA_RM_INDEX_INVALID) {
124 result = -EINVAL;
125 goto bail;
126 }
127 graph->resource_table[resource_index] = resource;
128bail:
129 return result;
130}
131
132/**
133 * ipa_rm_dep_graph_remove() - removes resource from graph
134 * @graph: [in] dependency graph
135 * @resource: [in] resource to add
136 *
137 * Returns: 0 on success, negative on failure
138 */
139int ipa_rm_dep_graph_remove(struct ipa_rm_dep_graph *graph,
140 enum ipa_rm_resource_name resource_name)
141{
142 if (!graph)
143 return -EINVAL;
144 graph->resource_table[resource_name] = NULL;
145
146 return 0;
147}
148
149/**
150 * ipa_rm_dep_graph_add_dependency() - adds dependency between
151 * two nodes in graph
152 * @graph: [in] dependency graph
153 * @resource_name: [in] resource to add
154 * @depends_on_name: [in] resource to add
155 * @userspace_dep: [in] operation requested by userspace ?
156 *
157 * Returns: 0 on success, negative on failure
158 */
159int ipa_rm_dep_graph_add_dependency(struct ipa_rm_dep_graph *graph,
160 enum ipa_rm_resource_name resource_name,
161 enum ipa_rm_resource_name depends_on_name,
162 bool userspace_dep)
163{
164 struct ipa_rm_resource *dependent = NULL;
165 struct ipa_rm_resource *dependency = NULL;
166 int result;
167
168 if (!graph ||
169 !IPA_RM_RESORCE_IS_PROD(resource_name) ||
170 !IPA_RM_RESORCE_IS_CONS(depends_on_name)) {
171 IPA_RM_ERR("invalid params\n");
172 result = -EINVAL;
173 goto bail;
174 }
175 if (ipa_rm_dep_graph_get_resource(graph,
176 resource_name,
177 &dependent)) {
178 IPA_RM_ERR("%s does not exist\n",
179 ipa_rm_resource_str(resource_name));
180 result = -EINVAL;
181 goto bail;
182 }
183 if (ipa_rm_dep_graph_get_resource(graph,
184 depends_on_name,
185 &dependency)) {
186 IPA_RM_ERR("%s does not exist\n",
187 ipa_rm_resource_str(depends_on_name));
188 result = -EINVAL;
189 goto bail;
190 }
191 result = ipa_rm_resource_add_dependency(dependent, dependency,
192 userspace_dep);
193bail:
194 IPA_RM_DBG("EXIT with %d\n", result);
195
196 return result;
197}
198
199/**
200 * ipa_rm_dep_graph_delete_dependency() - deleted dependency between
201 * two nodes in graph
202 * @graph: [in] dependency graph
203 * @resource_name: [in] resource to delete
204 * @depends_on_name: [in] resource to delete
205 * @userspace_dep: [in] operation requested by userspace ?
206 *
207 * Returns: 0 on success, negative on failure
208 *
209 */
210int ipa_rm_dep_graph_delete_dependency(struct ipa_rm_dep_graph *graph,
211 enum ipa_rm_resource_name resource_name,
212 enum ipa_rm_resource_name depends_on_name,
213 bool userspace_dep)
214{
215 struct ipa_rm_resource *dependent = NULL;
216 struct ipa_rm_resource *dependency = NULL;
217 int result;
218
219 if (!graph ||
220 !IPA_RM_RESORCE_IS_PROD(resource_name) ||
221 !IPA_RM_RESORCE_IS_CONS(depends_on_name)) {
222 IPA_RM_ERR("invalid params\n");
223 result = -EINVAL;
224 goto bail;
225 }
226
227 if (ipa_rm_dep_graph_get_resource(graph,
228 resource_name,
229 &dependent)) {
Sunil Paidimarri4dbe11c2016-11-09 17:29:06 -0800230 IPA_RM_DBG("%s does not exist\n",
Amir Levy9659e592016-10-27 18:08:27 +0300231 ipa_rm_resource_str(resource_name));
232 result = -EINVAL;
233 goto bail;
234 }
235
236 if (ipa_rm_dep_graph_get_resource(graph,
237 depends_on_name,
238 &dependency)) {
Sunil Paidimarri4dbe11c2016-11-09 17:29:06 -0800239 IPA_RM_DBG("%s does not exist\n",
Amir Levy9659e592016-10-27 18:08:27 +0300240 ipa_rm_resource_str(depends_on_name));
241 result = -EINVAL;
242 goto bail;
243 }
244
245 result = ipa_rm_resource_delete_dependency(dependent, dependency,
246 userspace_dep);
247bail:
248 IPA_RM_DBG("EXIT with %d\n", result);
249
250 return result;
251}