diff options
author | Vijayakumar Subbu <vsubbu@nvidia.com> | 2016-07-28 01:29:15 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2016-09-29 16:17:46 -0400 |
commit | b17d9708c9e9930778de43de1edf1385acb13ebd (patch) | |
tree | fc485e96cc19575d463c61c8b80a09dd89745f3f /drivers/gpu/nvgpu/boardobj/boardobjgrp.c | |
parent | 27b47b1969d7d9cdd3de9fd6f0131ad357f4b0fa (diff) |
gpu: nvgpu: Add dGPU clocks support
JIRA DNVGPU-45
Change-Id: I237ce81e31b036c05c82d46eea8694ffe1c2e3df
Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com>
Signed-off-by: Vijayakumar Subbu <vsubbu@nvidia.com>
Reviewed-on: http://git-master/r/1205849
(cherry picked from commit 9a4006f76b75a8ad525e7aa5ad1f609aaae49126)
Reviewed-on: http://git-master/r/1227256
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/boardobj/boardobjgrp.c')
-rw-r--r-- | drivers/gpu/nvgpu/boardobj/boardobjgrp.c | 697 |
1 files changed, 697 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/boardobj/boardobjgrp.c b/drivers/gpu/nvgpu/boardobj/boardobjgrp.c new file mode 100644 index 00000000..dfa394ed --- /dev/null +++ b/drivers/gpu/nvgpu/boardobj/boardobjgrp.c | |||
@@ -0,0 +1,697 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | */ | ||
13 | |||
14 | #include "gk20a/gk20a.h" | ||
15 | #include "gk20a/pmu_gk20a.h" | ||
16 | #include "boardobjgrp.h" | ||
17 | #include "ctrl/ctrlboardobj.h" | ||
18 | #include "boardobj.h" | ||
19 | |||
20 | static boardobjgrp_objinsert boardobjgrp_objinsert_final; | ||
21 | static boardobjgrp_objgetbyidx boardobjgrp_objgetbyidx_final; | ||
22 | static boardobjgrp_objgetnext boardobjgrp_objgetnext_final; | ||
23 | static boardobjgrp_objremoveanddestroy boardobjgrp_objremoveanddestroy_final; | ||
24 | static boardobjgrp_pmudatainstget boardobjgrp_pmudatainstget_stub; | ||
25 | static boardobjgrp_pmustatusinstget boardobjgrp_pmustatusinstget_stub; | ||
26 | static u32 boardobjgrp_pmucmdsend(struct gk20a *g, | ||
27 | struct boardobjgrp *pboardobjgrp, | ||
28 | struct boardobjgrp_pmu_cmd *pcmd); | ||
29 | struct boardobjgrp_pmucmdhandler_params { | ||
30 | /* Pointer to the BOARDOBJGRP associated with this CMD */ | ||
31 | struct boardobjgrp *pboardobjgrp; | ||
32 | /* Pointer to structure representing this NV_PMU_BOARDOBJ_CMD_GRP */ | ||
33 | struct boardobjgrp_pmu_cmd *pcmd; | ||
34 | /* Boolean indicating whether the PMU successfully handled the CMD */ | ||
35 | u32 success; | ||
36 | }; | ||
37 | |||
38 | u32 boardobjgrp_construct_super(struct boardobjgrp *pboardobjgrp) | ||
39 | { | ||
40 | gk20a_dbg_info(""); | ||
41 | |||
42 | if (pboardobjgrp == NULL) | ||
43 | return -EINVAL; | ||
44 | |||
45 | if (pboardobjgrp->ppobjects == NULL) | ||
46 | return -EINVAL; | ||
47 | |||
48 | if (pboardobjgrp->mask == NULL) | ||
49 | return -EINVAL; | ||
50 | |||
51 | pboardobjgrp->objmask = 0; | ||
52 | |||
53 | pboardobjgrp->classid = 0; | ||
54 | pboardobjgrp->pmu.unitid = BOARDOBJGRP_UNIT_ID_INVALID; | ||
55 | pboardobjgrp->pmu.classid = BOARDOBJGRP_GRP_CLASS_ID_INVALID; | ||
56 | pboardobjgrp->pmu.set.id = BOARDOBJGRP_GRP_CMD_ID_INVALID; | ||
57 | pboardobjgrp->pmu.getstatus.id = BOARDOBJGRP_GRP_CMD_ID_INVALID; | ||
58 | |||
59 | /* Initialize basic interfaces */ | ||
60 | pboardobjgrp->destruct = boardobjgrp_destruct_super; | ||
61 | pboardobjgrp->objinsert = boardobjgrp_objinsert_final; | ||
62 | pboardobjgrp->objgetbyidx = boardobjgrp_objgetbyidx_final; | ||
63 | pboardobjgrp->objgetnext = boardobjgrp_objgetnext_final; | ||
64 | pboardobjgrp->objremoveanddestroy = | ||
65 | boardobjgrp_objremoveanddestroy_final; | ||
66 | |||
67 | pboardobjgrp->pmuinithandle = boardobjgrp_pmuinithandle_impl; | ||
68 | pboardobjgrp->pmuhdrdatainit = boardobjgrp_pmuhdrdatainit_super; | ||
69 | pboardobjgrp->pmudatainit = boardobjgrp_pmudatainit_super; | ||
70 | pboardobjgrp->pmuset = boardobjgrp_pmuset_impl; | ||
71 | pboardobjgrp->pmugetstatus = boardobjgrp_pmugetstatus_impl; | ||
72 | |||
73 | pboardobjgrp->pmudatainstget = boardobjgrp_pmudatainstget_stub; | ||
74 | pboardobjgrp->pmustatusinstget = boardobjgrp_pmustatusinstget_stub; | ||
75 | |||
76 | pboardobjgrp->objmaxidx = CTRL_BOARDOBJ_IDX_INVALID; | ||
77 | pboardobjgrp->bconstructed = true; | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | u32 boardobjgrp_destruct_impl(struct boardobjgrp *pboardobjgrp) | ||
83 | { | ||
84 | gk20a_dbg_info(""); | ||
85 | |||
86 | if (pboardobjgrp == NULL) | ||
87 | return -EINVAL; | ||
88 | |||
89 | if (!pboardobjgrp->bconstructed) | ||
90 | return 0; | ||
91 | |||
92 | return pboardobjgrp->destruct(pboardobjgrp); | ||
93 | } | ||
94 | |||
95 | u32 boardobjgrp_destruct_super(struct boardobjgrp *pboardobjgrp) | ||
96 | { | ||
97 | struct boardobj *pboardobj; | ||
98 | u32 status = 0; | ||
99 | u32 stat; | ||
100 | u8 index; | ||
101 | |||
102 | gk20a_dbg_info(""); | ||
103 | |||
104 | if (pboardobjgrp->mask == NULL) | ||
105 | return -EINVAL; | ||
106 | if (pboardobjgrp->ppobjects == NULL) | ||
107 | return -EINVAL; | ||
108 | |||
109 | BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) { | ||
110 | stat = pboardobjgrp->objremoveanddestroy(pboardobjgrp, index); | ||
111 | if (status == 0) | ||
112 | status = stat; | ||
113 | |||
114 | pboardobjgrp->ppobjects[index] = NULL; | ||
115 | pboardobjgrp->objmask &= ~BIT(index); | ||
116 | } | ||
117 | |||
118 | pboardobjgrp->objmask = 0; | ||
119 | |||
120 | if (pboardobjgrp->objmaxidx != CTRL_BOARDOBJ_IDX_INVALID) { | ||
121 | if (status == 0) | ||
122 | status = -EINVAL; | ||
123 | |||
124 | WARN_ON(true); | ||
125 | } | ||
126 | |||
127 | /* Destroy the PMU CMD data */ | ||
128 | stat = boardobjgrp_pmucmd_destroy_impl(&pboardobjgrp->pmu.set); | ||
129 | if (status == 0) | ||
130 | status = stat; | ||
131 | |||
132 | stat = boardobjgrp_pmucmd_destroy_impl(&pboardobjgrp->pmu.getstatus); | ||
133 | if (status == 0) | ||
134 | status = stat; | ||
135 | |||
136 | pboardobjgrp->bconstructed = false; | ||
137 | |||
138 | return status; | ||
139 | } | ||
140 | |||
141 | u32 boardobjgrp_pmucmd_construct_impl(struct gk20a *g, struct boardobjgrp | ||
142 | *pboardobjgrp, struct boardobjgrp_pmu_cmd *cmd, u8 id, u8 msgid, | ||
143 | u8 hdrsize, u8 entrysize, u16 fbsize) | ||
144 | { | ||
145 | gk20a_dbg_info(""); | ||
146 | |||
147 | /* Copy the parameters into the CMD*/ | ||
148 | cmd->id = id; | ||
149 | cmd->msgid = msgid; | ||
150 | cmd->hdrsize = hdrsize; | ||
151 | cmd->entrysize = entrysize; | ||
152 | cmd->fbsize = fbsize; | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | |||
158 | u32 boardobjgrp_pmucmd_destroy_impl(struct boardobjgrp_pmu_cmd *cmd) | ||
159 | { | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | u32 boardobjgrp_pmucmd_pmuinithandle_impl(struct gk20a *g, | ||
164 | struct boardobjgrp *pboardobjgrp, | ||
165 | struct boardobjgrp_pmu_cmd *pcmd) | ||
166 | { | ||
167 | u32 status = 0; | ||
168 | struct mem_desc *sysmem_desc = &pcmd->surf.sysmem_desc; | ||
169 | |||
170 | gk20a_dbg_info(""); | ||
171 | |||
172 | if (pcmd->id == BOARDOBJGRP_GRP_CMD_ID_INVALID) | ||
173 | goto boardobjgrp_pmucmd_pmuinithandle_exit; | ||
174 | |||
175 | gk20a_pmu_sysmem_surface_alloc(g, sysmem_desc, pcmd->fbsize); | ||
176 | |||
177 | pcmd->buf = (struct nv_pmu_boardobjgrp_super *)sysmem_desc->cpu_va; | ||
178 | |||
179 | boardobjgrp_pmucmd_pmuinithandle_exit: | ||
180 | return status; | ||
181 | } | ||
182 | |||
183 | u32 boardobjgrp_pmuinithandle_impl(struct gk20a *g, | ||
184 | struct boardobjgrp *pboardobjgrp) | ||
185 | { | ||
186 | u32 status = 0; | ||
187 | |||
188 | gk20a_dbg_info(""); | ||
189 | |||
190 | status = boardobjgrp_pmucmd_pmuinithandle_impl(g, pboardobjgrp, | ||
191 | &pboardobjgrp->pmu.set); | ||
192 | if (status) { | ||
193 | gk20a_err(dev_from_gk20a(g), "failed to init pmu set cmd"); | ||
194 | goto boardobjgrp_pmuinithandle_exit; | ||
195 | } | ||
196 | |||
197 | status = boardobjgrp_pmucmd_pmuinithandle_impl(g, pboardobjgrp, | ||
198 | &pboardobjgrp->pmu.getstatus); | ||
199 | if (status) { | ||
200 | gk20a_err(dev_from_gk20a(g), "failed to init get status command"); | ||
201 | goto boardobjgrp_pmuinithandle_exit; | ||
202 | } | ||
203 | |||
204 | /* If the GRP_SET CMD has not been allocated, nothing left to do. */ | ||
205 | if (((pboardobjgrp->pmu.set.id) == BOARDOBJGRP_GRP_CMD_ID_INVALID) || | ||
206 | (BOARDOBJGRP_IS_EMPTY(pboardobjgrp))) | ||
207 | goto boardobjgrp_pmuinithandle_exit; | ||
208 | |||
209 | /* Send the BOARDOBJGRP to the pmu via RM_PMU_BOARDOBJ_CMD_GRP. */ | ||
210 | status = pboardobjgrp->pmuset(g, pboardobjgrp); | ||
211 | if (status) | ||
212 | gk20a_err(dev_from_gk20a(g), "failed to send boardobg grp to PMU"); | ||
213 | |||
214 | boardobjgrp_pmuinithandle_exit: | ||
215 | return status; | ||
216 | } | ||
217 | |||
218 | |||
219 | u32 boardobjgrp_pmuhdrdatainit_super(struct gk20a *g, struct boardobjgrp | ||
220 | *pboardobjgrp, struct nv_pmu_boardobjgrp_super *pboardobjgrppmu, | ||
221 | struct boardobjgrpmask *mask) | ||
222 | { | ||
223 | gk20a_dbg_info(""); | ||
224 | |||
225 | if (pboardobjgrp == NULL) | ||
226 | return -EINVAL; | ||
227 | if (pboardobjgrppmu == NULL) | ||
228 | return -EINVAL; | ||
229 | pboardobjgrppmu->type = pboardobjgrp->type; | ||
230 | pboardobjgrppmu->class_id = pboardobjgrp->classid; | ||
231 | pboardobjgrppmu->obj_slots = BOARDOBJGRP_PMU_SLOTS_GET(pboardobjgrp); | ||
232 | |||
233 | gk20a_dbg_info(" Done"); | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | u32 boardobjgrp_pmudatainstget_stub(struct gk20a *g, | ||
238 | struct nv_pmu_boardobjgrp *boardobjgrppmu, | ||
239 | struct nv_pmu_boardobj **ppboardobjpmudata, u8 idx) | ||
240 | { | ||
241 | gk20a_dbg_info(""); | ||
242 | return -EINVAL; | ||
243 | } | ||
244 | |||
245 | |||
246 | u32 boardobjgrp_pmustatusinstget_stub(struct gk20a *g, void *pboardobjgrppmu, | ||
247 | struct nv_pmu_boardobj_query **ppBoardobjpmustatus, u8 idx) | ||
248 | { | ||
249 | gk20a_dbg_info(""); | ||
250 | return -EINVAL; | ||
251 | } | ||
252 | |||
253 | |||
254 | u32 boardobjgrp_pmudatainit_super(struct gk20a *g, struct boardobjgrp | ||
255 | *pboardobjgrp, struct nv_pmu_boardobjgrp_super *pboardobjgrppmu) | ||
256 | { | ||
257 | u32 status = 0; | ||
258 | struct boardobj *pboardobj = NULL; | ||
259 | struct nv_pmu_boardobj *ppmudata = NULL; | ||
260 | u8 index; | ||
261 | |||
262 | gk20a_dbg_info(""); | ||
263 | |||
264 | if (pboardobjgrp == NULL) | ||
265 | return -EINVAL; | ||
266 | if (pboardobjgrppmu == NULL) | ||
267 | return -EINVAL; | ||
268 | |||
269 | /* Initialize the PMU HDR data.*/ | ||
270 | status = pboardobjgrp->pmuhdrdatainit(g, pboardobjgrp, pboardobjgrppmu, | ||
271 | pboardobjgrp->mask); | ||
272 | if (status) { | ||
273 | gk20a_err(dev_from_gk20a(g), | ||
274 | "unable to init boardobjgrp pmuhdr data"); | ||
275 | goto boardobjgrppmudatainit_super_done; | ||
276 | } | ||
277 | |||
278 | BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) { | ||
279 | status = pboardobjgrp->pmudatainstget(g, | ||
280 | (struct nv_pmu_boardobjgrp *)pboardobjgrppmu, | ||
281 | &ppmudata, index); | ||
282 | if (status) { | ||
283 | gk20a_err(dev_from_gk20a(g), | ||
284 | "could not get object instance"); | ||
285 | goto boardobjgrppmudatainit_super_done; | ||
286 | } | ||
287 | |||
288 | /* Initialize the PMU Data and send to PMU */ | ||
289 | status = pboardobj->pmudatainit(g, pboardobj, ppmudata); | ||
290 | if (status) { | ||
291 | gk20a_err(dev_from_gk20a(g), | ||
292 | "could not parse pmu for device %d", index); | ||
293 | goto boardobjgrppmudatainit_super_done; | ||
294 | } | ||
295 | } | ||
296 | |||
297 | boardobjgrppmudatainit_super_done: | ||
298 | gk20a_dbg_info(" Done"); | ||
299 | return status; | ||
300 | } | ||
301 | |||
302 | u32 boardobjgrp_pmuset_impl(struct gk20a *g, struct boardobjgrp *pboardobjgrp) | ||
303 | { | ||
304 | u32 status = 0; | ||
305 | |||
306 | gk20a_dbg_info(""); | ||
307 | |||
308 | if (pboardobjgrp == NULL) | ||
309 | return -EINVAL; | ||
310 | |||
311 | if (!pboardobjgrp->bconstructed) | ||
312 | return -EINVAL; | ||
313 | |||
314 | if (pboardobjgrp->pmu.unitid == BOARDOBJGRP_UNIT_ID_INVALID) | ||
315 | return -EINVAL; | ||
316 | |||
317 | if (pboardobjgrp->pmu.classid == BOARDOBJGRP_GRP_CLASS_ID_INVALID) | ||
318 | return -EINVAL; | ||
319 | |||
320 | if (pboardobjgrp->pmu.set.id == BOARDOBJGRP_GRP_CMD_ID_INVALID) | ||
321 | return -EINVAL; | ||
322 | |||
323 | if ((pboardobjgrp->pmu.set.hdrsize == 0) || | ||
324 | (pboardobjgrp->pmu.set.entrysize == 0) || | ||
325 | (pboardobjgrp->pmu.set.buf == NULL)) | ||
326 | return -EINVAL; | ||
327 | |||
328 | /* If no objects in the group, return early */ | ||
329 | if (BOARDOBJGRP_IS_EMPTY(pboardobjgrp)) | ||
330 | return -EINVAL; | ||
331 | |||
332 | /* Initialize PMU buffer with BOARDOBJGRP data. */ | ||
333 | memset(pboardobjgrp->pmu.set.buf, 0x0, pboardobjgrp->pmu.set.fbsize); | ||
334 | status = pboardobjgrp->pmudatainit(g, pboardobjgrp, | ||
335 | pboardobjgrp->pmu.set.buf); | ||
336 | if (status) { | ||
337 | gk20a_err(dev_from_gk20a(g), | ||
338 | "could not parse pmu data"); | ||
339 | goto boardobjgrp_pmuset_exit; | ||
340 | } | ||
341 | |||
342 | /* | ||
343 | * Reset the boolean that indicates set status for most recent | ||
344 | * instance of BOARDOBJGRP. | ||
345 | */ | ||
346 | pboardobjgrp->pmu.bset = false; | ||
347 | |||
348 | /* Send the SET PMU CMD to the PMU */ | ||
349 | status = boardobjgrp_pmucmdsend(g, pboardobjgrp, | ||
350 | &pboardobjgrp->pmu.set); | ||
351 | if (status) { | ||
352 | gk20a_err(dev_from_gk20a(g), "could not send SET CMD to PMU"); | ||
353 | goto boardobjgrp_pmuset_exit; | ||
354 | } | ||
355 | |||
356 | pboardobjgrp->pmu.bset = true; | ||
357 | |||
358 | boardobjgrp_pmuset_exit: | ||
359 | return status; | ||
360 | } | ||
361 | |||
362 | u32 | ||
363 | boardobjgrp_pmugetstatus_impl(struct gk20a *g, struct boardobjgrp *pboardobjgrp, | ||
364 | struct boardobjgrpmask *mask) | ||
365 | { | ||
366 | u32 status = 0; | ||
367 | |||
368 | gk20a_dbg_info(""); | ||
369 | |||
370 | if (pboardobjgrp == NULL) | ||
371 | return -EINVAL; | ||
372 | |||
373 | if (!pboardobjgrp->bconstructed) | ||
374 | return -EINVAL; | ||
375 | |||
376 | if (pboardobjgrp->pmu.unitid == BOARDOBJGRP_UNIT_ID_INVALID) | ||
377 | return -EINVAL; | ||
378 | |||
379 | if (pboardobjgrp->pmu.classid == BOARDOBJGRP_GRP_CLASS_ID_INVALID) | ||
380 | return -EINVAL; | ||
381 | |||
382 | if (pboardobjgrp->pmu.set.id == BOARDOBJGRP_GRP_CMD_ID_INVALID) | ||
383 | return -EINVAL; | ||
384 | |||
385 | if ((pboardobjgrp->pmu.set.hdrsize == 0) || | ||
386 | (pboardobjgrp->pmu.set.entrysize == 0) || | ||
387 | (pboardobjgrp->pmu.set.buf == NULL)) | ||
388 | return -EINVAL; | ||
389 | |||
390 | /* If no objects in the group, return early */ | ||
391 | if (BOARDOBJGRP_IS_EMPTY(pboardobjgrp)) | ||
392 | return -EINVAL; | ||
393 | |||
394 | /* | ||
395 | * Can only GET_STATUS if the BOARDOBJGRP has been previously SET to the | ||
396 | * PMU | ||
397 | */ | ||
398 | if (!pboardobjgrp->pmu.bset) | ||
399 | return -EINVAL; | ||
400 | |||
401 | /* | ||
402 | * Initialize PMU buffer with the mask of BOARDOBJGRPs for which to | ||
403 | * retrieve status | ||
404 | */ | ||
405 | |||
406 | memset(pboardobjgrp->pmu.getstatus.buf, 0x0, | ||
407 | pboardobjgrp->pmu.getstatus.fbsize); | ||
408 | status = pboardobjgrp->pmuhdrdatainit(g, pboardobjgrp, | ||
409 | pboardobjgrp->pmu.getstatus.buf, mask); | ||
410 | if (status) { | ||
411 | gk20a_err(dev_from_gk20a(g), "could not init PMU HDR data"); | ||
412 | goto boardobjgrp_pmugetstatus_exit; | ||
413 | } | ||
414 | |||
415 | /* Send the GET_STATUS PMU CMD to the PMU */ | ||
416 | status = boardobjgrp_pmucmdsend(g, pboardobjgrp, | ||
417 | &pboardobjgrp->pmu.getstatus); | ||
418 | if (status) { | ||
419 | gk20a_err(dev_from_gk20a(g), | ||
420 | "could not send GET_STATUS cmd to PMU"); | ||
421 | goto boardobjgrp_pmugetstatus_exit; | ||
422 | } | ||
423 | |||
424 | boardobjgrp_pmugetstatus_exit: | ||
425 | return status; | ||
426 | } | ||
427 | |||
428 | static u32 | ||
429 | boardobjgrp_objinsert_final(struct boardobjgrp *pboardobjgrp, | ||
430 | struct boardobj *pboardobj, u8 index) | ||
431 | { | ||
432 | |||
433 | gk20a_dbg_info(""); | ||
434 | |||
435 | if (pboardobjgrp == NULL) | ||
436 | return -EINVAL; | ||
437 | |||
438 | if (pboardobj == NULL) | ||
439 | return -EINVAL; | ||
440 | |||
441 | if (index > pboardobjgrp->objslots) | ||
442 | return -EINVAL; | ||
443 | |||
444 | if (pboardobjgrp->ppobjects[index] != NULL) | ||
445 | return -EINVAL; | ||
446 | |||
447 | /* | ||
448 | * Check that this BOARDOBJ has not already been added to a | ||
449 | * BOARDOBJGRP | ||
450 | */ | ||
451 | if (pboardobj->idx != CTRL_BOARDOBJ_IDX_INVALID) | ||
452 | return -EINVAL; | ||
453 | |||
454 | pboardobjgrp->ppobjects[index] = pboardobj; | ||
455 | pboardobjgrp->objmaxidx = BOARDOBJGRP_IS_EMPTY(pboardobjgrp) ? | ||
456 | index : max(pboardobjgrp->objmaxidx, index); | ||
457 | pboardobj->idx = index; | ||
458 | |||
459 | pboardobjgrp->objmask |= BIT(index); | ||
460 | |||
461 | gk20a_dbg_info(" Done"); | ||
462 | |||
463 | return boardobjgrpmask_bitset(pboardobjgrp->mask, index); | ||
464 | } | ||
465 | |||
466 | static struct boardobj *boardobjgrp_objgetbyidx_final( | ||
467 | struct boardobjgrp *pboardobjgrp, u8 index) | ||
468 | { | ||
469 | if (!boardobjgrp_idxisvalid(pboardobjgrp, index)) | ||
470 | return NULL; | ||
471 | return pboardobjgrp->ppobjects[index]; | ||
472 | } | ||
473 | |||
474 | static struct boardobj *boardobjgrp_objgetnext_final( | ||
475 | struct boardobjgrp *pboardobjgrp, u8 *currentindex, | ||
476 | struct boardobjgrpmask *mask) | ||
477 | { | ||
478 | struct boardobj *pboardobjnext = NULL; | ||
479 | u8 objmaxidx; | ||
480 | u8 index; | ||
481 | |||
482 | if (currentindex == NULL) | ||
483 | return NULL; | ||
484 | |||
485 | if (pboardobjgrp == NULL) | ||
486 | return NULL; | ||
487 | |||
488 | /* Search from next element unless first object was requested */ | ||
489 | index = (*currentindex != CTRL_BOARDOBJ_IDX_INVALID) ? | ||
490 | (*currentindex + 1) : 0; | ||
491 | |||
492 | /* For the cases below in which we have to return NULL */ | ||
493 | *currentindex = CTRL_BOARDOBJ_IDX_INVALID; | ||
494 | |||
495 | |||
496 | /* Validate provided mask */ | ||
497 | if (mask != NULL) { | ||
498 | if (!(boardobjgrpmask_sizeeq(pboardobjgrp->mask, mask))) | ||
499 | return NULL; | ||
500 | } | ||
501 | |||
502 | objmaxidx = pboardobjgrp->objmaxidx; | ||
503 | |||
504 | if (objmaxidx != CTRL_BOARDOBJ_IDX_INVALID) { | ||
505 | for (; index <= objmaxidx; index++) { | ||
506 | pboardobjnext = pboardobjgrp->ppobjects[index]; | ||
507 | if (pboardobjnext != NULL) { | ||
508 | /* Filter results using client provided mask.*/ | ||
509 | if (mask != NULL) { | ||
510 | if (!boardobjgrpmask_bitget(mask, | ||
511 | index)) { | ||
512 | pboardobjnext = NULL; | ||
513 | continue; | ||
514 | } | ||
515 | } | ||
516 | *currentindex = index; | ||
517 | break; | ||
518 | } | ||
519 | } | ||
520 | } | ||
521 | |||
522 | return pboardobjnext; | ||
523 | } | ||
524 | |||
525 | static u32 boardobjgrp_objremoveanddestroy_final( | ||
526 | struct boardobjgrp *pboardobjgrp, | ||
527 | u8 index) | ||
528 | { | ||
529 | u32 status = 0; | ||
530 | u32 stat; | ||
531 | |||
532 | gk20a_dbg_info(""); | ||
533 | |||
534 | if (!boardobjgrp_idxisvalid(pboardobjgrp, index)) | ||
535 | return -EINVAL; | ||
536 | |||
537 | if (pboardobjgrp->objmaxidx == CTRL_BOARDOBJ_IDX_INVALID) | ||
538 | return -EINVAL; | ||
539 | |||
540 | status = pboardobjgrp->ppobjects[index]->destruct( | ||
541 | pboardobjgrp->ppobjects[index]); | ||
542 | |||
543 | pboardobjgrp->ppobjects[index] = NULL; | ||
544 | |||
545 | pboardobjgrp->objmask &= ~BIT(index); | ||
546 | |||
547 | stat = boardobjgrpmask_bitclr(pboardobjgrp->mask, index); | ||
548 | if (stat) { | ||
549 | if (status == 0) | ||
550 | status = stat; | ||
551 | } | ||
552 | |||
553 | /* objmaxidx requires update only if that very object was removed */ | ||
554 | if (pboardobjgrp->objmaxidx == index) { | ||
555 | pboardobjgrp->objmaxidx = | ||
556 | boardobjgrpmask_bitidxhighest(pboardobjgrp->mask); | ||
557 | } | ||
558 | |||
559 | return status; | ||
560 | } | ||
561 | |||
562 | void boardobjgrpe32hdrset(struct nv_pmu_boardobjgrp *hdr, u32 objmask) | ||
563 | { | ||
564 | u32 slots = objmask; | ||
565 | |||
566 | gk20a_dbg_info(""); | ||
567 | |||
568 | HIGHESTBITIDX_32(slots); | ||
569 | slots++; | ||
570 | |||
571 | hdr->super.type = CTRL_BOARDOBJGRP_TYPE_E32; | ||
572 | hdr->super.class_id = 0; | ||
573 | hdr->super.obj_slots = (u8)slots; | ||
574 | hdr->obj_mask = objmask; | ||
575 | } | ||
576 | |||
577 | static void boardobjgrp_pmucmdhandler(struct gk20a *g, struct pmu_msg *msg, | ||
578 | void *param, u32 handle, u32 status) | ||
579 | { | ||
580 | struct nv_pmu_boardobj_msg_grp *pgrpmsg; | ||
581 | struct boardobjgrp_pmucmdhandler_params *phandlerparams = | ||
582 | (struct boardobjgrp_pmucmdhandler_params *)param; | ||
583 | struct boardobjgrp *pboardobjgrp = phandlerparams->pboardobjgrp; | ||
584 | struct boardobjgrp_pmu_cmd *pgrpcmd = phandlerparams->pcmd; | ||
585 | |||
586 | gk20a_dbg_info(""); | ||
587 | |||
588 | pgrpmsg = &msg->msg.boardobj.grp; | ||
589 | |||
590 | if (pgrpmsg->class_id != pboardobjgrp->pmu.classid) { | ||
591 | gk20a_err(dev_from_gk20a(g), | ||
592 | "Unrecognized GRP type: unit %x class id=0x%02x cmd id %x", | ||
593 | msg->hdr.unit_id, pboardobjgrp->pmu.classid, | ||
594 | pgrpcmd->id); | ||
595 | return; | ||
596 | } | ||
597 | |||
598 | if (msg->msg.boardobj.msg_type != pgrpcmd->msgid) { | ||
599 | gk20a_err(dev_from_gk20a(g), | ||
600 | "unsupported msg for unit %x class %x cmd id %x msg %x", | ||
601 | msg->hdr.unit_id, pboardobjgrp->pmu.classid, | ||
602 | pgrpcmd->id, msg->msg.boardobj.msg_type); | ||
603 | return; | ||
604 | } | ||
605 | |||
606 | if (msg->msg.boardobj.grp_set.flcn_status != 0) { | ||
607 | gk20a_err(dev_from_gk20a(g), | ||
608 | "cmd abort for unit %x class %x cmd id %x status %x", | ||
609 | msg->hdr.unit_id, pboardobjgrp->pmu.classid, | ||
610 | pgrpcmd->id, | ||
611 | msg->msg.boardobj.grp_set.flcn_status); | ||
612 | return; | ||
613 | } | ||
614 | |||
615 | phandlerparams->success = pgrpmsg->b_success ? 1 : 0; | ||
616 | |||
617 | if (!pgrpmsg->b_success) { | ||
618 | gk20a_err(dev_from_gk20a(g), | ||
619 | "failed GRPCMD: msgtype=0x%x, classid=0x%x, cmd id %x", | ||
620 | pgrpmsg->msg_type, pgrpmsg->class_id, | ||
621 | pgrpcmd->id); | ||
622 | return; | ||
623 | } | ||
624 | } | ||
625 | |||
626 | static u32 boardobjgrp_pmucmdsend(struct gk20a *g, | ||
627 | struct boardobjgrp *pboardobjgrp, | ||
628 | struct boardobjgrp_pmu_cmd *pcmd) | ||
629 | { | ||
630 | struct boardobjgrp_pmucmdhandler_params handlerparams = { 0 }; | ||
631 | struct pmu_payload payload = { {0} }; | ||
632 | struct nv_pmu_boardobj_cmd_grp *pgrpcmd; | ||
633 | struct pmu_cmd cmd; | ||
634 | u32 seqdesc; | ||
635 | u32 status = 0; | ||
636 | |||
637 | gk20a_dbg_info(""); | ||
638 | |||
639 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | ||
640 | cmd.hdr.unit_id = pboardobjgrp->pmu.unitid; | ||
641 | cmd.hdr.size = sizeof(struct nv_pmu_boardobj_cmd_grp) + | ||
642 | sizeof(struct pmu_hdr); | ||
643 | |||
644 | pgrpcmd = &cmd.cmd.boardobj.grp; | ||
645 | pgrpcmd->cmd_type = pcmd->id; | ||
646 | pgrpcmd->class_id = pboardobjgrp->pmu.classid; | ||
647 | pgrpcmd->grp.hdr_size = pcmd->hdrsize; | ||
648 | pgrpcmd->grp.entry_size = pcmd->entrysize; | ||
649 | |||
650 | /* | ||
651 | * alloc mem in vidmem & copy constructed pmu boardobjgrp data from | ||
652 | * sysmem to vidmem | ||
653 | */ | ||
654 | gk20a_pmu_vidmem_surface_alloc(g, &pcmd->surf.vidmem_desc, | ||
655 | pcmd->fbsize); | ||
656 | gk20a_pmu_surface_describe(g, &pcmd->surf.vidmem_desc, | ||
657 | &pgrpcmd->grp.fb); | ||
658 | gk20a_mem_wr_n(g, &pcmd->surf.vidmem_desc, 0, pcmd->buf, pcmd->fbsize); | ||
659 | |||
660 | /* | ||
661 | * PMU reads command from sysmem so assigned | ||
662 | * "payload.in.buf = pcmd->buf" | ||
663 | * but PMU access pmu boardobjgrp data from vidmem copied above | ||
664 | */ | ||
665 | payload.in.buf = pcmd->buf; | ||
666 | payload.in.size = max(pcmd->hdrsize, pcmd->entrysize); | ||
667 | payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED; | ||
668 | payload.in.offset = offsetof(struct nv_pmu_boardobj_cmd_grp, grp); | ||
669 | |||
670 | /* Setup the handler params to communicate back results.*/ | ||
671 | handlerparams.pboardobjgrp = pboardobjgrp; | ||
672 | handlerparams.pcmd = pcmd; | ||
673 | handlerparams.success = 0; | ||
674 | |||
675 | status = gk20a_pmu_cmd_post(g, &cmd, NULL, &payload, | ||
676 | PMU_COMMAND_QUEUE_LPQ, | ||
677 | boardobjgrp_pmucmdhandler, | ||
678 | (void *)&handlerparams, | ||
679 | &seqdesc, ~0); | ||
680 | if (status) { | ||
681 | gk20a_err(dev_from_gk20a(g), | ||
682 | "unable to post boardobj grp cmd for unit %x cmd id %x", | ||
683 | cmd.hdr.unit_id, pcmd->id); | ||
684 | goto boardobjgrp_pmucmdsend_exit; | ||
685 | } | ||
686 | pmu_wait_message_cond(&g->pmu, | ||
687 | gk20a_get_gr_idle_timeout(g), | ||
688 | &handlerparams.success, 1); | ||
689 | if (handlerparams.success == 0) { | ||
690 | gk20a_err(dev_from_gk20a(g), "could not process cmd\n"); | ||
691 | status = -ETIMEDOUT; | ||
692 | goto boardobjgrp_pmucmdsend_exit; | ||
693 | } | ||
694 | |||
695 | boardobjgrp_pmucmdsend_exit: | ||
696 | return status; | ||
697 | } | ||