blob: 83651202268126581cb87e6c11ac2b319cf7d950 [file] [log] [blame]
Skylar Changa9516582017-05-09 11:36:47 -07001/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Amir Levy9659e592016-10-27 18:08:27 +03002 *
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_i.h"
15
16/**
17 * ipa_rm_peers_list_get_resource_index() - resource name to index
18 * of this resource in corresponding peers list
19 * @resource_name: [in] resource name
20 *
21 * Returns: resource index mapping, IPA_RM_INDEX_INVALID
22 * in case provided resource name isn't contained in enum
23 * ipa_rm_resource_name.
24 *
25 */
26static int ipa_rm_peers_list_get_resource_index(
27 enum ipa_rm_resource_name resource_name)
28{
29 int resource_index = IPA_RM_INDEX_INVALID;
30
31 if (IPA_RM_RESORCE_IS_PROD(resource_name))
32 resource_index = ipa_rm_prod_index(resource_name);
33 else if (IPA_RM_RESORCE_IS_CONS(resource_name)) {
34 resource_index = ipa_rm_cons_index(resource_name);
Amir Levy9659e592016-10-27 18:08:27 +030035 }
36
37 return resource_index;
38}
39
40static bool ipa_rm_peers_list_check_index(int index,
41 struct ipa_rm_peers_list *peers_list)
42{
43 return !(index > peers_list->max_peers || index < 0);
44}
45
46/**
47 * ipa_rm_peers_list_create() - creates the peers list
48 *
49 * @max_peers: maximum number of peers in new list
50 * @peers_list: [out] newly created peers list
51 *
52 * Returns: 0 in case of SUCCESS, negative otherwise
53 */
54int ipa_rm_peers_list_create(int max_peers,
55 struct ipa_rm_peers_list **peers_list)
56{
57 int result;
58
59 *peers_list = kzalloc(sizeof(**peers_list), GFP_ATOMIC);
60 if (!*peers_list) {
61 IPA_RM_ERR("no mem\n");
62 result = -ENOMEM;
63 goto bail;
64 }
65
66 (*peers_list)->max_peers = max_peers;
67 (*peers_list)->peers = kzalloc((*peers_list)->max_peers *
68 sizeof(*((*peers_list)->peers)), GFP_ATOMIC);
69 if (!((*peers_list)->peers)) {
70 IPA_RM_ERR("no mem\n");
71 result = -ENOMEM;
72 goto list_alloc_fail;
73 }
74
75 return 0;
76
77list_alloc_fail:
78 kfree(*peers_list);
79bail:
80 return result;
81}
82
83/**
84 * ipa_rm_peers_list_delete() - deletes the peers list
85 *
86 * @peers_list: peers list
87 *
88 */
89void ipa_rm_peers_list_delete(struct ipa_rm_peers_list *peers_list)
90{
91 if (peers_list) {
92 kfree(peers_list->peers);
93 kfree(peers_list);
94 }
95}
96
97/**
98 * ipa_rm_peers_list_remove_peer() - removes peer from the list
99 *
100 * @peers_list: peers list
101 * @resource_name: name of the resource to remove
102 *
103 */
104void ipa_rm_peers_list_remove_peer(
105 struct ipa_rm_peers_list *peers_list,
106 enum ipa_rm_resource_name resource_name)
107{
108 if (!peers_list)
109 return;
110
111 peers_list->peers[ipa_rm_peers_list_get_resource_index(
112 resource_name)].resource = NULL;
113 peers_list->peers[ipa_rm_peers_list_get_resource_index(
114 resource_name)].userspace_dep = false;
115 peers_list->peers_count--;
116}
117
118/**
119 * ipa_rm_peers_list_add_peer() - adds peer to the list
120 *
121 * @peers_list: peers list
122 * @resource: resource to add
123 *
124 */
125void ipa_rm_peers_list_add_peer(
126 struct ipa_rm_peers_list *peers_list,
127 struct ipa_rm_resource *resource,
128 bool userspace_dep)
129{
130 if (!peers_list || !resource)
131 return;
132
133 peers_list->peers[ipa_rm_peers_list_get_resource_index(
134 resource->name)].resource = resource;
135 peers_list->peers[ipa_rm_peers_list_get_resource_index(
136 resource->name)].userspace_dep = userspace_dep;
137 peers_list->peers_count++;
138}
139
140/**
141 * ipa_rm_peers_list_is_empty() - checks
142 * if resource peers list is empty
143 *
144 * @peers_list: peers list
145 *
146 * Returns: true if the list is empty, false otherwise
147 */
148bool ipa_rm_peers_list_is_empty(struct ipa_rm_peers_list *peers_list)
149{
150 bool result = true;
151
152 if (!peers_list)
153 goto bail;
154
155 if (peers_list->peers_count > 0)
156 result = false;
157bail:
158 return result;
159}
160
161/**
162 * ipa_rm_peers_list_has_last_peer() - checks
163 * if resource peers list has exactly one peer
164 *
165 * @peers_list: peers list
166 *
167 * Returns: true if the list has exactly one peer, false otherwise
168 */
169bool ipa_rm_peers_list_has_last_peer(
170 struct ipa_rm_peers_list *peers_list)
171{
172 bool result = false;
173
174 if (!peers_list)
175 goto bail;
176
177 if (peers_list->peers_count == 1)
178 result = true;
179bail:
180 return result;
181}
182
183/**
184 * ipa_rm_peers_list_check_dependency() - check dependency
185 * between 2 peer lists
186 * @resource_peers: first peers list
187 * @resource_name: first peers list resource name
188 * @depends_on_peers: second peers list
189 * @depends_on_name: second peers list resource name
190 * @userspace_dep: [out] dependency was created by userspace
191 *
192 * Returns: true if there is dependency, false otherwise
193 *
194 */
195bool ipa_rm_peers_list_check_dependency(
196 struct ipa_rm_peers_list *resource_peers,
197 enum ipa_rm_resource_name resource_name,
198 struct ipa_rm_peers_list *depends_on_peers,
199 enum ipa_rm_resource_name depends_on_name,
200 bool *userspace_dep)
201{
202 bool result = false;
203 int resource_index;
204
205 if (!resource_peers || !depends_on_peers || !userspace_dep)
206 return result;
207
208 resource_index = ipa_rm_peers_list_get_resource_index(depends_on_name);
209 if (resource_peers->peers[resource_index].resource != NULL) {
210 result = true;
211 *userspace_dep = resource_peers->peers[resource_index].
212 userspace_dep;
213 }
214
215 resource_index = ipa_rm_peers_list_get_resource_index(resource_name);
216 if (depends_on_peers->peers[resource_index].resource != NULL) {
217 result = true;
218 *userspace_dep = depends_on_peers->peers[resource_index].
219 userspace_dep;
220 }
221
222 return result;
223}
224
225/**
226 * ipa_rm_peers_list_get_resource() - get resource by
227 * resource index
228 * @resource_index: resource index
229 * @resource_peers: peers list
230 *
231 * Returns: the resource if found, NULL otherwise
232 */
233struct ipa_rm_resource *ipa_rm_peers_list_get_resource(int resource_index,
234 struct ipa_rm_peers_list *resource_peers)
235{
236 struct ipa_rm_resource *result = NULL;
237
238 if (!ipa_rm_peers_list_check_index(resource_index, resource_peers))
239 goto bail;
240
241 result = resource_peers->peers[resource_index].resource;
242bail:
243 return result;
244}
245
246/**
247 * ipa_rm_peers_list_get_userspace_dep() - returns whether resource dependency
248 * was added by userspace
249 * @resource_index: resource index
250 * @resource_peers: peers list
251 *
252 * Returns: true if dependency was added by userspace, false by kernel
253 */
254bool ipa_rm_peers_list_get_userspace_dep(int resource_index,
255 struct ipa_rm_peers_list *resource_peers)
256{
257 bool result = false;
258
259 if (!ipa_rm_peers_list_check_index(resource_index, resource_peers))
260 goto bail;
261
262 result = resource_peers->peers[resource_index].userspace_dep;
263bail:
264 return result;
265}
266
267/**
268 * ipa_rm_peers_list_get_size() - get peers list sise
269 *
270 * @peers_list: peers list
271 *
272 * Returns: the size of the peers list
273 */
274int ipa_rm_peers_list_get_size(struct ipa_rm_peers_list *peers_list)
275{
276 return peers_list->max_peers;
277}