aboutsummaryrefslogtreecommitdiffstats
path: root/include/boardobj/boardobjgrp.c
diff options
context:
space:
mode:
authorJoshua Bakita <bakitajoshua@gmail.com>2023-06-28 18:24:25 -0400
committerJoshua Bakita <bakitajoshua@gmail.com>2023-06-28 18:24:25 -0400
commit01e6fac4d61fdd7fff5433942ec93fc2ea1e4df1 (patch)
tree4ef34501728a087be24f4ba0af90f91486bf780b /include/boardobj/boardobjgrp.c
parent306a03d18b305e4e573be3b2931978fa10679eb9 (diff)
Include nvgpu headers
These are needed to build on NVIDIA's Jetson boards for the time being. Only a couple structs are required, so it should be fairly easy to remove this dependency at some point in the future.
Diffstat (limited to 'include/boardobj/boardobjgrp.c')
-rw-r--r--include/boardobj/boardobjgrp.c1046
1 files changed, 1046 insertions, 0 deletions
diff --git a/include/boardobj/boardobjgrp.c b/include/boardobj/boardobjgrp.c
new file mode 100644
index 0000000..6832070
--- /dev/null
+++ b/include/boardobj/boardobjgrp.c
@@ -0,0 +1,1046 @@
1/*
2* Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
3*
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21*/
22#include <nvgpu/bug.h>
23#include <nvgpu/gk20a.h>
24
25#include "boardobjgrp.h"
26#include "ctrl/ctrlboardobj.h"
27#include "boardobj.h"
28
29static boardobjgrp_objinsert boardobjgrp_objinsert_final;
30static boardobjgrp_objgetbyidx boardobjgrp_objgetbyidx_final;
31static boardobjgrp_objgetnext boardobjgrp_objgetnext_final;
32static boardobjgrp_objremoveanddestroy boardobjgrp_objremoveanddestroy_final;
33static boardobjgrp_pmudatainstget boardobjgrp_pmudatainstget_stub;
34static boardobjgrp_pmustatusinstget boardobjgrp_pmustatusinstget_stub;
35static int boardobjgrp_pmucmdsend(struct gk20a *g,
36 struct boardobjgrp *pboardobjgrp,
37 struct boardobjgrp_pmu_cmd *pcmd);
38static int boardobjgrp_pmucmdsend_rpc(struct gk20a *g,
39 struct boardobjgrp *pboardobjgrp,
40 struct boardobjgrp_pmu_cmd *pcmd,
41 bool copy_out);
42struct boardobjgrp_pmucmdhandler_params {
43 /* Pointer to the BOARDOBJGRP associated with this CMD */
44 struct boardobjgrp *pboardobjgrp;
45 /* Pointer to structure representing this NV_PMU_BOARDOBJ_CMD_GRP */
46 struct boardobjgrp_pmu_cmd *pcmd;
47 /* Boolean indicating whether the PMU successfully handled the CMD */
48 u32 success;
49};
50
51int boardobjgrp_construct_super(struct gk20a *g,
52 struct boardobjgrp *pboardobjgrp)
53{
54 nvgpu_log_info(g, " ");
55
56 if (pboardobjgrp == NULL) {
57 return -EINVAL;
58 }
59
60 if (pboardobjgrp->ppobjects == NULL) {
61 return -EINVAL;
62 }
63
64 if (pboardobjgrp->mask == NULL) {
65 return -EINVAL;
66 }
67
68 pboardobjgrp->g = g;
69 pboardobjgrp->objmask = 0;
70
71 pboardobjgrp->classid = 0;
72 pboardobjgrp->pmu.unitid = BOARDOBJGRP_UNIT_ID_INVALID;
73 pboardobjgrp->pmu.classid = BOARDOBJGRP_GRP_CLASS_ID_INVALID;
74 pboardobjgrp->pmu.bset = false;
75 pboardobjgrp->pmu.rpc_func_id = BOARDOBJGRP_GRP_RPC_FUNC_ID_INVALID;
76 pboardobjgrp->pmu.set.id = BOARDOBJGRP_GRP_CMD_ID_INVALID;
77 pboardobjgrp->pmu.getstatus.id = BOARDOBJGRP_GRP_CMD_ID_INVALID;
78
79 /* Initialize basic interfaces */
80 pboardobjgrp->destruct = boardobjgrp_destruct_super;
81 pboardobjgrp->objinsert = boardobjgrp_objinsert_final;
82 pboardobjgrp->objgetbyidx = boardobjgrp_objgetbyidx_final;
83 pboardobjgrp->objgetnext = boardobjgrp_objgetnext_final;
84 pboardobjgrp->objremoveanddestroy =
85 boardobjgrp_objremoveanddestroy_final;
86
87 pboardobjgrp->pmuinithandle = boardobjgrp_pmuinithandle_impl;
88 pboardobjgrp->pmuhdrdatainit = boardobjgrp_pmuhdrdatainit_super;
89 pboardobjgrp->pmudatainit = boardobjgrp_pmudatainit_super;
90 pboardobjgrp->pmuset =
91 g->ops.pmu_ver.boardobj.boardobjgrp_pmuset_impl;
92 pboardobjgrp->pmugetstatus =
93 g->ops.pmu_ver.boardobj.boardobjgrp_pmugetstatus_impl;
94
95 pboardobjgrp->pmudatainstget = boardobjgrp_pmudatainstget_stub;
96 pboardobjgrp->pmustatusinstget = boardobjgrp_pmustatusinstget_stub;
97
98 pboardobjgrp->objmaxidx = CTRL_BOARDOBJ_IDX_INVALID;
99 pboardobjgrp->bconstructed = true;
100
101 nvgpu_list_add(&pboardobjgrp->node, &g->boardobjgrp_head);
102
103 return 0;
104}
105
106int boardobjgrp_destruct_impl(struct boardobjgrp *pboardobjgrp)
107{
108 struct gk20a *g = pboardobjgrp->g;
109
110 nvgpu_log_info(g, " ");
111
112 if (pboardobjgrp == NULL) {
113 return -EINVAL;
114 }
115
116 if (!pboardobjgrp->bconstructed) {
117 return 0;
118 }
119
120 return pboardobjgrp->destruct(pboardobjgrp);
121}
122
123int boardobjgrp_destruct_super(struct boardobjgrp *pboardobjgrp)
124{
125 struct boardobj *pboardobj;
126 struct gk20a *g = pboardobjgrp->g;
127 int status = 0;
128 int stat;
129 u8 index;
130
131 nvgpu_log_info(g, " ");
132
133 if (pboardobjgrp->mask == NULL) {
134 return -EINVAL;
135 }
136 if (pboardobjgrp->ppobjects == NULL) {
137 return -EINVAL;
138 }
139
140 BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) {
141 stat = pboardobjgrp->objremoveanddestroy(pboardobjgrp, index);
142 if (status == 0) {
143 status = stat;
144 }
145
146 pboardobjgrp->ppobjects[index] = NULL;
147 pboardobjgrp->objmask &= ~BIT(index);
148 }
149
150 pboardobjgrp->objmask = 0;
151
152 if (pboardobjgrp->objmaxidx != CTRL_BOARDOBJ_IDX_INVALID) {
153 if (status == 0) {
154 status = -EINVAL;
155 }
156
157 WARN_ON(true);
158 }
159
160 /* Destroy the PMU CMD data */
161 stat = boardobjgrp_pmucmd_destroy_impl(g, &pboardobjgrp->pmu.set);
162 if (status == 0) {
163 status = stat;
164 }
165
166 stat = boardobjgrp_pmucmd_destroy_impl(g, &pboardobjgrp->pmu.getstatus);
167 if (status == 0) {
168 status = stat;
169 }
170
171 nvgpu_list_del(&pboardobjgrp->node);
172
173 pboardobjgrp->bconstructed = false;
174
175 return status;
176}
177
178int boardobjgrp_pmucmd_construct_impl(struct gk20a *g, struct boardobjgrp
179 *pboardobjgrp, struct boardobjgrp_pmu_cmd *cmd, u8 id, u8 msgid,
180 u16 hdrsize, u16 entrysize, u16 fbsize, u32 ss_offset, u8 rpc_func_id)
181{
182 nvgpu_log_info(g, " ");
183
184 /* Copy the parameters into the CMD*/
185 cmd->id = id;
186 cmd->msgid = msgid;
187 cmd->hdrsize = (u8) hdrsize;
188 cmd->entrysize = (u8) entrysize;
189 cmd->fbsize = fbsize;
190
191 return 0;
192}
193
194int boardobjgrp_pmucmd_construct_impl_v1(struct gk20a *g, struct boardobjgrp
195 *pboardobjgrp, struct boardobjgrp_pmu_cmd *cmd, u8 id, u8 msgid,
196 u16 hdrsize, u16 entrysize, u16 fbsize, u32 ss_offset, u8 rpc_func_id)
197{
198 nvgpu_log_fn(g, " ");
199
200 /* Copy the parameters into the CMD*/
201 cmd->dmem_buffer_size = ((hdrsize > entrysize) ? hdrsize : entrysize);
202 cmd->super_surface_offset = ss_offset;
203 pboardobjgrp->pmu.rpc_func_id = rpc_func_id;
204 cmd->fbsize = fbsize;
205
206 nvgpu_log_fn(g, "DONE");
207 return 0;
208}
209
210int boardobjgrp_pmucmd_destroy_impl(struct gk20a *g,
211 struct boardobjgrp_pmu_cmd *cmd)
212{
213 struct nvgpu_mem *mem = &cmd->surf.sysmem_desc;
214
215 nvgpu_pmu_surface_free(g, mem);
216 return 0;
217}
218
219int is_boardobjgrp_pmucmd_id_valid_v0(struct gk20a *g,
220 struct boardobjgrp *pboardobjgrp,
221 struct boardobjgrp_pmu_cmd *pcmd)
222{
223 int err = 0;
224
225 if (pcmd->id == BOARDOBJGRP_GRP_CMD_ID_INVALID) {
226 err = -EINVAL;
227 }
228
229 return err;
230}
231
232int is_boardobjgrp_pmucmd_id_valid_v1(struct gk20a *g,
233 struct boardobjgrp *pboardobjgrp,
234 struct boardobjgrp_pmu_cmd *cmd)
235{
236 int err = 0;
237
238 if (pboardobjgrp->pmu.rpc_func_id ==
239 BOARDOBJGRP_GRP_RPC_FUNC_ID_INVALID) {
240 err = -EINVAL;
241 }
242
243 return err;
244}
245
246int boardobjgrp_pmucmd_pmuinithandle_impl(struct gk20a *g,
247 struct boardobjgrp *pboardobjgrp,
248 struct boardobjgrp_pmu_cmd *pcmd)
249{
250 int status = 0;
251 struct nvgpu_mem *sysmem_desc = &pcmd->surf.sysmem_desc;
252
253 nvgpu_log_info(g, " ");
254
255 if (g->ops.pmu_ver.boardobj.is_boardobjgrp_pmucmd_id_valid(g,
256 pboardobjgrp, pcmd)) {
257 goto boardobjgrp_pmucmd_pmuinithandle_exit;
258 }
259
260 if (!pcmd->fbsize) {
261 goto boardobjgrp_pmucmd_pmuinithandle_exit;
262 }
263
264 nvgpu_pmu_sysmem_surface_alloc(g, sysmem_desc, pcmd->fbsize);
265 /* we only have got sysmem later this will get copied to vidmem
266 surface*/
267 pcmd->surf.vidmem_desc.size = 0;
268
269 pcmd->buf = (struct nv_pmu_boardobjgrp_super *)sysmem_desc->cpu_va;
270
271boardobjgrp_pmucmd_pmuinithandle_exit:
272 return status;
273}
274
275int boardobjgrp_pmuinithandle_impl(struct gk20a *g,
276 struct boardobjgrp *pboardobjgrp)
277{
278 int status = 0;
279
280 nvgpu_log_info(g, " ");
281
282 status = boardobjgrp_pmucmd_pmuinithandle_impl(g, pboardobjgrp,
283 &pboardobjgrp->pmu.set);
284 if (status) {
285 nvgpu_err(g, "failed to init pmu set cmd");
286 goto boardobjgrp_pmuinithandle_exit;
287 }
288
289 status = boardobjgrp_pmucmd_pmuinithandle_impl(g, pboardobjgrp,
290 &pboardobjgrp->pmu.getstatus);
291 if (status) {
292 nvgpu_err(g, "failed to init get status command");
293 goto boardobjgrp_pmuinithandle_exit;
294 }
295
296 /* If the GRP_SET CMD has not been allocated, nothing left to do. */
297 if ((g->ops.pmu_ver.boardobj.is_boardobjgrp_pmucmd_id_valid(g,
298 pboardobjgrp, &pboardobjgrp->pmu.set))||
299 (BOARDOBJGRP_IS_EMPTY(pboardobjgrp))) {
300 goto boardobjgrp_pmuinithandle_exit;
301 }
302
303 /* Send the BOARDOBJGRP to the pmu via RM_PMU_BOARDOBJ_CMD_GRP. */
304 status = pboardobjgrp->pmuset(g, pboardobjgrp);
305 if (status) {
306 nvgpu_err(g, "failed to send boardobg grp to PMU");
307 }
308
309boardobjgrp_pmuinithandle_exit:
310 return status;
311}
312
313
314int boardobjgrp_pmuhdrdatainit_super(struct gk20a *g, struct boardobjgrp
315 *pboardobjgrp, struct nv_pmu_boardobjgrp_super *pboardobjgrppmu,
316 struct boardobjgrpmask *mask)
317{
318 nvgpu_log_info(g, " ");
319
320 if (pboardobjgrp == NULL) {
321 return -EINVAL;
322 }
323 if (pboardobjgrppmu == NULL) {
324 return -EINVAL;
325 }
326 pboardobjgrppmu->type = pboardobjgrp->type;
327 pboardobjgrppmu->class_id = pboardobjgrp->classid;
328 pboardobjgrppmu->obj_slots = BOARDOBJGRP_PMU_SLOTS_GET(pboardobjgrp);
329 pboardobjgrppmu->flags = 0;
330
331 nvgpu_log_info(g, " Done");
332 return 0;
333}
334
335static int boardobjgrp_pmudatainstget_stub(struct gk20a *g,
336 struct nv_pmu_boardobjgrp *boardobjgrppmu,
337 struct nv_pmu_boardobj **ppboardobjpmudata, u8 idx)
338{
339 nvgpu_log_info(g, " ");
340 return -EINVAL;
341}
342
343
344static int boardobjgrp_pmustatusinstget_stub(struct gk20a *g,
345 void *pboardobjgrppmu,
346 struct nv_pmu_boardobj_query **ppBoardobjpmustatus, u8 idx)
347{
348 nvgpu_log_info(g, " ");
349 return -EINVAL;
350}
351
352int boardobjgrp_pmudatainit_legacy(struct gk20a *g,
353 struct boardobjgrp *pboardobjgrp,
354 struct nv_pmu_boardobjgrp_super *pboardobjgrppmu)
355{
356 int status = 0;
357 struct boardobj *pboardobj = NULL;
358 struct nv_pmu_boardobj *ppmudata = NULL;
359 u8 index;
360
361 nvgpu_log_info(g, " ");
362
363 if (pboardobjgrp == NULL) {
364 return -EINVAL;
365 }
366 if (pboardobjgrppmu == NULL) {
367 return -EINVAL;
368 }
369
370 boardobjgrpe32hdrset((struct nv_pmu_boardobjgrp *)pboardobjgrppmu,
371 pboardobjgrp->objmask);
372
373 BOARDOBJGRP_FOR_EACH_INDEX_IN_MASK(32, index, pboardobjgrp->objmask) {
374 /* Obtain pointer to the current instance of the Object from the Group */
375 pboardobj = pboardobjgrp->objgetbyidx(pboardobjgrp, index);
376 if (NULL == pboardobj) {
377 nvgpu_err(g, "could not get object instance");
378 status = -EINVAL;
379 goto boardobjgrppmudatainit_legacy_done;
380 }
381
382 status = pboardobjgrp->pmudatainstget(g,
383 (struct nv_pmu_boardobjgrp *)pboardobjgrppmu,
384 &ppmudata, index);
385 if (status) {
386 nvgpu_err(g, "could not get object instance");
387 goto boardobjgrppmudatainit_legacy_done;
388 }
389
390 /* Initialize the PMU Data */
391 status = pboardobj->pmudatainit(g, pboardobj, ppmudata);
392 if (status) {
393 nvgpu_err(g,
394 "could not parse pmu for device %d", index);
395 goto boardobjgrppmudatainit_legacy_done;
396 }
397 }
398 BOARDOBJGRP_FOR_EACH_INDEX_IN_MASK_END
399
400boardobjgrppmudatainit_legacy_done:
401 nvgpu_log_info(g, " Done");
402 return status;
403}
404
405int boardobjgrp_pmudatainit_super(struct gk20a *g, struct boardobjgrp
406 *pboardobjgrp, struct nv_pmu_boardobjgrp_super *pboardobjgrppmu)
407{
408 int status = 0;
409 struct boardobj *pboardobj = NULL;
410 struct nv_pmu_boardobj *ppmudata = NULL;
411 u8 index;
412
413 nvgpu_log_info(g, " ");
414
415 if (pboardobjgrp == NULL) {
416 return -EINVAL;
417 }
418 if (pboardobjgrppmu == NULL) {
419 return -EINVAL;
420 }
421
422 /* Initialize the PMU HDR data.*/
423 status = pboardobjgrp->pmuhdrdatainit(g, pboardobjgrp, pboardobjgrppmu,
424 pboardobjgrp->mask);
425 if (status) {
426 nvgpu_err(g, "unable to init boardobjgrp pmuhdr data");
427 goto boardobjgrppmudatainit_super_done;
428 }
429
430 BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) {
431 status = pboardobjgrp->pmudatainstget(g,
432 (struct nv_pmu_boardobjgrp *)pboardobjgrppmu,
433 &ppmudata, index);
434 if (status) {
435 nvgpu_err(g, "could not get object instance");
436 goto boardobjgrppmudatainit_super_done;
437 }
438
439 /* Initialize the PMU Data and send to PMU */
440 status = pboardobj->pmudatainit(g, pboardobj, ppmudata);
441 if (status) {
442 nvgpu_err(g,
443 "could not parse pmu for device %d", index);
444 goto boardobjgrppmudatainit_super_done;
445 }
446 }
447
448boardobjgrppmudatainit_super_done:
449 nvgpu_log_info(g, " Done");
450 return status;
451}
452
453static int check_boardobjgrp_param(struct gk20a *g,
454 struct boardobjgrp *pboardobjgrp)
455{
456 if (pboardobjgrp == NULL) {
457 return -EINVAL;
458 }
459
460 if (!pboardobjgrp->bconstructed) {
461 return -EINVAL;
462 }
463
464 if (pboardobjgrp->pmu.unitid == BOARDOBJGRP_UNIT_ID_INVALID) {
465 return -EINVAL;
466 }
467
468 if (pboardobjgrp->pmu.classid == BOARDOBJGRP_GRP_CLASS_ID_INVALID) {
469 return -EINVAL;
470 }
471
472 /* If no objects in the group, return early */
473 if (BOARDOBJGRP_IS_EMPTY(pboardobjgrp)) {
474 return -EINVAL;
475 }
476
477 return 0;
478}
479
480int boardobjgrp_pmuset_impl(struct gk20a *g, struct boardobjgrp *pboardobjgrp)
481{
482 int status = 0;
483 struct boardobjgrp_pmu_cmd *pcmd =
484 (struct boardobjgrp_pmu_cmd *)(&pboardobjgrp->pmu.set);
485
486 nvgpu_log_info(g, " ");
487
488 if (check_boardobjgrp_param(g, pboardobjgrp)) {
489 return -EINVAL;
490 }
491
492 if (pboardobjgrp->pmu.set.id == BOARDOBJGRP_GRP_CMD_ID_INVALID) {
493 return -EINVAL;
494 }
495
496 if ((pcmd->hdrsize == 0) ||
497 (pcmd->entrysize == 0) ||
498 (pcmd->buf == NULL)) {
499 return -EINVAL;
500 }
501
502 /* Initialize PMU buffer with BOARDOBJGRP data. */
503 memset(pcmd->buf, 0x0, pcmd->fbsize);
504 status = pboardobjgrp->pmudatainit(g, pboardobjgrp,
505 pcmd->buf);
506 if (status) {
507 nvgpu_err(g, "could not parse pmu data");
508 goto boardobjgrp_pmuset_exit;
509 }
510
511 /*
512 * Reset the boolean that indicates set status for most recent
513 * instance of BOARDOBJGRP.
514 */
515 pboardobjgrp->pmu.bset = false;
516
517 /*
518 * alloc mem in vidmem & copy constructed pmu boardobjgrp data from
519 * sysmem to vidmem
520 */
521 if (pcmd->surf.vidmem_desc.size == 0) {
522 nvgpu_pmu_vidmem_surface_alloc(g, &pcmd->surf.vidmem_desc,
523 pcmd->fbsize);
524 }
525 nvgpu_mem_wr_n(g, &pcmd->surf.vidmem_desc, 0, pcmd->buf, pcmd->fbsize);
526
527 /* Send the SET PMU CMD to the PMU */
528 status = boardobjgrp_pmucmdsend(g, pboardobjgrp,
529 pcmd);
530 if (status) {
531 nvgpu_err(g, "could not send SET CMD to PMU");
532 goto boardobjgrp_pmuset_exit;
533 }
534
535 pboardobjgrp->pmu.bset = true;
536
537boardobjgrp_pmuset_exit:
538 return status;
539}
540
541int boardobjgrp_pmuset_impl_v1(struct gk20a *g,
542 struct boardobjgrp *pboardobjgrp)
543{
544 struct nvgpu_pmu *pmu = &g->pmu;
545 int status = 0;
546 struct boardobjgrp_pmu_cmd *pcmd =
547 (struct boardobjgrp_pmu_cmd *)(&pboardobjgrp->pmu.set);
548
549 nvgpu_log_info(g, " ");
550
551 if (check_boardobjgrp_param(g, pboardobjgrp)) {
552 return -EINVAL;
553 }
554
555 if ((pcmd->buf == NULL) &&
556 (pboardobjgrp->pmu.rpc_func_id ==
557 BOARDOBJGRP_GRP_RPC_FUNC_ID_INVALID)) {
558 return -EINVAL;
559 }
560
561 /* Initialize PMU buffer with BOARDOBJGRP data. */
562 memset(pcmd->buf, 0x0, pcmd->fbsize);
563 status = pboardobjgrp->pmudatainit(g, pboardobjgrp,
564 pcmd->buf);
565 if (status) {
566 nvgpu_err(g, "could not parse pmu data");
567 goto boardobjgrp_pmuset_exit;
568 }
569
570 /*
571 * Reset the boolean that indicates set status
572 * for most recent instance of BOARDOBJGRP.
573 */
574 pboardobjgrp->pmu.bset = false;
575
576 /*
577 * copy constructed pmu boardobjgrp data from
578 * sysmem to pmu super surface present in FB
579 */
580 nvgpu_mem_wr_n(g, &pmu->super_surface_buf,
581 pcmd->super_surface_offset, pcmd->buf,
582 pcmd->fbsize);
583
584 /* Send the SET PMU CMD to the PMU using RPC*/
585 status = boardobjgrp_pmucmdsend_rpc(g, pboardobjgrp,
586 pcmd, false);
587 if (status) {
588 nvgpu_err(g, "could not send SET CMD to PMU");
589 goto boardobjgrp_pmuset_exit;
590 }
591
592 pboardobjgrp->pmu.bset = true;
593
594boardobjgrp_pmuset_exit:
595 return status;
596}
597
598int
599boardobjgrp_pmugetstatus_impl(struct gk20a *g, struct boardobjgrp *pboardobjgrp,
600 struct boardobjgrpmask *mask)
601{
602 int status = 0;
603 struct boardobjgrp_pmu_cmd *pcmd =
604 (struct boardobjgrp_pmu_cmd *)(&pboardobjgrp->pmu.getstatus);
605 struct boardobjgrp_pmu_cmd *pset =
606 (struct boardobjgrp_pmu_cmd *)(&pboardobjgrp->pmu.set);
607
608 nvgpu_log_info(g, " ");
609
610 if (check_boardobjgrp_param(g, pboardobjgrp)) {
611 return -EINVAL;
612 }
613
614 if (pset->id == BOARDOBJGRP_GRP_CMD_ID_INVALID) {
615 return -EINVAL;
616 }
617
618 if ((pcmd->hdrsize == 0) ||
619 (pcmd->entrysize == 0) ||
620 (pcmd->buf == NULL)) {
621 return -EINVAL;
622 }
623
624 /*
625 * Can only GET_STATUS if the BOARDOBJGRP has been previously SET to the
626 * PMU
627 */
628 if (!pboardobjgrp->pmu.bset) {
629 return -EINVAL;
630 }
631
632 /*
633 * alloc mem in vidmem & copy constructed pmu boardobjgrp data from
634 * sysmem to vidmem
635 */
636 if (pcmd->surf.vidmem_desc.size == 0) {
637 nvgpu_pmu_vidmem_surface_alloc(g, &pcmd->surf.vidmem_desc,
638 pcmd->fbsize);
639 }
640
641 /*
642 * Initialize PMU buffer with the mask of BOARDOBJGRPs for which to
643 * retrieve status
644 */
645
646 memset(pcmd->buf, 0x0, pcmd->fbsize);
647 status = pboardobjgrp->pmuhdrdatainit(g, pboardobjgrp,
648 pcmd->buf, mask);
649 if (status) {
650 nvgpu_err(g, "could not init PMU HDR data");
651 goto boardobjgrp_pmugetstatus_exit;
652 }
653
654 nvgpu_mem_wr_n(g, &pcmd->surf.vidmem_desc, 0, pset->buf, pset->hdrsize);
655 /* Send the GET_STATUS PMU CMD to the PMU */
656 status = boardobjgrp_pmucmdsend(g, pboardobjgrp,
657 &pboardobjgrp->pmu.getstatus);
658 if (status) {
659 nvgpu_err(g, "could not send GET_STATUS cmd to PMU");
660 goto boardobjgrp_pmugetstatus_exit;
661 }
662
663 /*copy the data back to sysmem buffer that belongs to command*/
664 nvgpu_mem_rd_n(g, &pcmd->surf.vidmem_desc, 0, pcmd->buf, pcmd->fbsize);
665
666boardobjgrp_pmugetstatus_exit:
667 return status;
668}
669
670int
671boardobjgrp_pmugetstatus_impl_v1(struct gk20a *g, struct boardobjgrp *pboardobjgrp,
672 struct boardobjgrpmask *mask)
673{
674 struct nvgpu_pmu *pmu = &g->pmu;
675 int status = 0;
676 struct boardobjgrp_pmu_cmd *pcmd =
677 (struct boardobjgrp_pmu_cmd *)(&pboardobjgrp->pmu.getstatus);
678
679 nvgpu_log_info(g, " ");
680
681 if (check_boardobjgrp_param(g, pboardobjgrp)) {
682 return -EINVAL;
683 }
684
685 if ((pcmd->buf == NULL) &&
686 (pboardobjgrp->pmu.rpc_func_id ==
687 BOARDOBJGRP_GRP_RPC_FUNC_ID_INVALID)) {
688 return -EINVAL;
689 }
690
691 /*
692 * Can only GET_STATUS if the BOARDOBJGRP has been
693 * previously SET to the PMU
694 */
695 if (!pboardobjgrp->pmu.bset) {
696 return -EINVAL;
697 }
698
699 /*
700 * Initialize PMU buffer with the mask of
701 * BOARDOBJGRPs for which to retrieve status
702 */
703 memset(pcmd->buf, 0x0, pcmd->fbsize);
704 status = pboardobjgrp->pmuhdrdatainit(g, pboardobjgrp,
705 pcmd->buf, mask);
706 if (status) {
707 nvgpu_err(g, "could not init PMU HDR data");
708 goto boardobjgrp_pmugetstatus_exit;
709 }
710
711 /*
712 * copy constructed pmu boardobjgrp data from
713 * sysmem to pmu super surface present in FB
714 */
715 nvgpu_mem_wr_n(g, &pmu->super_surface_buf, pcmd->super_surface_offset,
716 pcmd->buf, pcmd->fbsize);
717 /* Send the GET_STATUS PMU CMD to the PMU */
718 status = boardobjgrp_pmucmdsend_rpc(g, pboardobjgrp,
719 pcmd, true);
720 if (status) {
721 nvgpu_err(g, "could not send GET_STATUS cmd to PMU");
722 goto boardobjgrp_pmugetstatus_exit;
723 }
724
725 /*copy the data back to sysmem buffer that belongs to command*/
726 nvgpu_mem_rd_n(g, &pmu->super_surface_buf,pcmd->super_surface_offset,
727 pcmd->buf, pcmd->fbsize);
728
729boardobjgrp_pmugetstatus_exit:
730 return status;
731}
732
733static int
734boardobjgrp_objinsert_final(struct boardobjgrp *pboardobjgrp,
735 struct boardobj *pboardobj, u8 index)
736{
737 struct gk20a *g = pboardobjgrp->g;
738
739 nvgpu_log_info(g, " ");
740
741 if (pboardobjgrp == NULL) {
742 return -EINVAL;
743 }
744
745 if (pboardobj == NULL) {
746 return -EINVAL;
747 }
748
749 if (index > pboardobjgrp->objslots) {
750 return -EINVAL;
751 }
752
753 if (pboardobjgrp->ppobjects[index] != NULL) {
754 return -EINVAL;
755 }
756
757 /*
758 * Check that this BOARDOBJ has not already been added to a
759 * BOARDOBJGRP
760 */
761 if (pboardobj->idx != CTRL_BOARDOBJ_IDX_INVALID) {
762 return -EINVAL;
763 }
764
765 pboardobjgrp->ppobjects[index] = pboardobj;
766 pboardobjgrp->objmaxidx = (u8)(BOARDOBJGRP_IS_EMPTY(pboardobjgrp) ?
767 index : max(pboardobjgrp->objmaxidx, index));
768 pboardobj->idx = index;
769
770 pboardobjgrp->objmask |= BIT(index);
771
772 nvgpu_log_info(g, " Done");
773
774 return boardobjgrpmask_bitset(pboardobjgrp->mask, index);
775}
776
777static struct boardobj *boardobjgrp_objgetbyidx_final(
778 struct boardobjgrp *pboardobjgrp, u8 index)
779{
780 if (!boardobjgrp_idxisvalid(pboardobjgrp, index)) {
781 return NULL;
782 }
783 return pboardobjgrp->ppobjects[index];
784}
785
786static struct boardobj *boardobjgrp_objgetnext_final(
787 struct boardobjgrp *pboardobjgrp, u8 *currentindex,
788 struct boardobjgrpmask *mask)
789{
790 struct boardobj *pboardobjnext = NULL;
791 u8 objmaxidx;
792 u8 index;
793
794 if (currentindex == NULL) {
795 return NULL;
796 }
797
798 if (pboardobjgrp == NULL) {
799 return NULL;
800 }
801
802 /* Search from next element unless first object was requested */
803 index = (*currentindex != CTRL_BOARDOBJ_IDX_INVALID) ?
804 (*currentindex + 1) : 0;
805
806 /* For the cases below in which we have to return NULL */
807 *currentindex = CTRL_BOARDOBJ_IDX_INVALID;
808
809
810 /* Validate provided mask */
811 if (mask != NULL) {
812 if (!(boardobjgrpmask_sizeeq(pboardobjgrp->mask, mask))) {
813 return NULL;
814 }
815 }
816
817 objmaxidx = pboardobjgrp->objmaxidx;
818
819 if (objmaxidx != CTRL_BOARDOBJ_IDX_INVALID) {
820 for (; index <= objmaxidx; index++) {
821 pboardobjnext = pboardobjgrp->ppobjects[index];
822 if (pboardobjnext != NULL) {
823 /* Filter results using client provided mask.*/
824 if (mask != NULL) {
825 if (!boardobjgrpmask_bitget(mask,
826 index)) {
827 pboardobjnext = NULL;
828 continue;
829 }
830 }
831 *currentindex = index;
832 break;
833 }
834 }
835 }
836
837 return pboardobjnext;
838}
839
840static int boardobjgrp_objremoveanddestroy_final(
841 struct boardobjgrp *pboardobjgrp,
842 u8 index)
843{
844 int status = 0;
845 int stat;
846 struct gk20a *g = pboardobjgrp->g;
847
848 nvgpu_log_info(g, " ");
849
850 if (!boardobjgrp_idxisvalid(pboardobjgrp, index)) {
851 return -EINVAL;
852 }
853
854 if (pboardobjgrp->objmaxidx == CTRL_BOARDOBJ_IDX_INVALID) {
855 return -EINVAL;
856 }
857
858 status = pboardobjgrp->ppobjects[index]->destruct(
859 pboardobjgrp->ppobjects[index]);
860
861 pboardobjgrp->ppobjects[index] = NULL;
862
863 pboardobjgrp->objmask &= ~BIT(index);
864
865 stat = boardobjgrpmask_bitclr(pboardobjgrp->mask, index);
866 if (stat) {
867 if (status == 0) {
868 status = stat;
869 }
870 }
871
872 /* objmaxidx requires update only if that very object was removed */
873 if (pboardobjgrp->objmaxidx == index) {
874 pboardobjgrp->objmaxidx =
875 boardobjgrpmask_bitidxhighest(pboardobjgrp->mask);
876 }
877
878 return status;
879}
880
881void boardobjgrpe32hdrset(struct nv_pmu_boardobjgrp *hdr, u32 objmask)
882{
883 u32 slots = objmask;
884
885 HIGHESTBITIDX_32(slots);
886 slots++;
887
888 hdr->super.type = CTRL_BOARDOBJGRP_TYPE_E32;
889 hdr->super.class_id = 0;
890 hdr->super.obj_slots = (u8)slots;
891 hdr->obj_mask = objmask;
892}
893
894static void boardobjgrp_pmucmdhandler(struct gk20a *g, struct pmu_msg *msg,
895 void *param, u32 handle, u32 status)
896{
897 struct nv_pmu_boardobj_msg_grp *pgrpmsg;
898 struct boardobjgrp_pmucmdhandler_params *phandlerparams =
899 (struct boardobjgrp_pmucmdhandler_params *)param;
900 struct boardobjgrp *pboardobjgrp = phandlerparams->pboardobjgrp;
901 struct boardobjgrp_pmu_cmd *pgrpcmd = phandlerparams->pcmd;
902
903 nvgpu_log_info(g, " ");
904
905 pgrpmsg = &msg->msg.boardobj.grp;
906
907 if (pgrpmsg->class_id != pboardobjgrp->pmu.classid) {
908 nvgpu_err(g,
909 "Unrecognized GRP type: unit %x class id=0x%02x cmd id %x",
910 msg->hdr.unit_id, pboardobjgrp->pmu.classid,
911 pgrpcmd->id);
912 return;
913 }
914
915 if (msg->msg.boardobj.msg_type != pgrpcmd->msgid) {
916 nvgpu_err(g,
917 "unsupported msg for unit %x class %x cmd id %x msg %x",
918 msg->hdr.unit_id, pboardobjgrp->pmu.classid,
919 pgrpcmd->id, msg->msg.boardobj.msg_type);
920 return;
921 }
922
923 if (msg->msg.boardobj.grp_set.flcn_status != 0) {
924 nvgpu_err(g,
925 "cmd abort for unit %x class %x cmd id %x status %x",
926 msg->hdr.unit_id, pboardobjgrp->pmu.classid,
927 pgrpcmd->id,
928 msg->msg.boardobj.grp_set.flcn_status);
929 return;
930 }
931
932 phandlerparams->success = pgrpmsg->b_success ? 1 : 0;
933
934 if (!pgrpmsg->b_success) {
935 nvgpu_err(g,
936 "failed GRPCMD: msgtype=0x%x, classid=0x%x, cmd id %x",
937 pgrpmsg->msg_type, pgrpmsg->class_id,
938 pgrpcmd->id);
939 return;
940 }
941}
942
943static int boardobjgrp_pmucmdsend(struct gk20a *g,
944 struct boardobjgrp *pboardobjgrp,
945 struct boardobjgrp_pmu_cmd *pcmd)
946{
947 struct boardobjgrp_pmucmdhandler_params handlerparams;
948 struct pmu_payload payload;
949 struct nv_pmu_boardobj_cmd_grp *pgrpcmd;
950 struct pmu_cmd cmd;
951 u32 seqdesc;
952 int status = 0;
953
954 nvgpu_log_info(g, " ");
955
956 memset(&payload, 0, sizeof(payload));
957 memset(&handlerparams, 0, sizeof(handlerparams));
958 memset(&cmd, 0, sizeof(struct pmu_cmd));
959 cmd.hdr.unit_id = pboardobjgrp->pmu.unitid;
960 cmd.hdr.size = sizeof(struct nv_pmu_boardobj_cmd_grp) +
961 sizeof(struct pmu_hdr);
962
963 pgrpcmd = &cmd.cmd.boardobj.grp;
964 pgrpcmd->cmd_type = pcmd->id;
965 pgrpcmd->class_id = pboardobjgrp->pmu.classid;
966 pgrpcmd->grp.hdr_size = pcmd->hdrsize;
967 pgrpcmd->grp.entry_size = pcmd->entrysize;
968
969 /*
970 * copy vidmem information to boardobj_cmd_grp
971 */
972 nvgpu_pmu_surface_describe(g, &pcmd->surf.vidmem_desc,
973 &pgrpcmd->grp.fb);
974
975 /*
976 * PMU reads command from sysmem so assigned
977 * "payload.in.buf = pcmd->buf"
978 * but PMU access pmu boardobjgrp data from vidmem copied above
979 */
980 payload.in.buf = pcmd->buf;
981 payload.in.size = max(pcmd->hdrsize, pcmd->entrysize);
982 payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED;
983 payload.in.offset = offsetof(struct nv_pmu_boardobj_cmd_grp, grp);
984
985 /* Setup the handler params to communicate back results.*/
986 handlerparams.pboardobjgrp = pboardobjgrp;
987 handlerparams.pcmd = pcmd;
988 handlerparams.success = 0;
989
990 status = nvgpu_pmu_cmd_post(g, &cmd, NULL, &payload,
991 PMU_COMMAND_QUEUE_LPQ,
992 boardobjgrp_pmucmdhandler,
993 (void *)&handlerparams,
994 &seqdesc, ~0);
995 if (status) {
996 nvgpu_err(g,
997 "unable to post boardobj grp cmd for unit %x cmd id %x",
998 cmd.hdr.unit_id, pcmd->id);
999 goto boardobjgrp_pmucmdsend_exit;
1000 }
1001 pmu_wait_message_cond(&g->pmu,
1002 gk20a_get_gr_idle_timeout(g),
1003 &handlerparams.success, 1);
1004 if (handlerparams.success == 0) {
1005 nvgpu_err(g, "could not process cmd");
1006 status = -ETIMEDOUT;
1007 goto boardobjgrp_pmucmdsend_exit;
1008 }
1009
1010boardobjgrp_pmucmdsend_exit:
1011 return status;
1012}
1013
1014static int boardobjgrp_pmucmdsend_rpc(struct gk20a *g,
1015 struct boardobjgrp *pboardobjgrp,
1016 struct boardobjgrp_pmu_cmd *pcmd,
1017 bool copy_out)
1018{
1019 struct nvgpu_pmu *pmu = &g->pmu;
1020 struct nv_pmu_rpc_struct_board_obj_grp_cmd rpc;
1021 int status = 0;
1022
1023 nvgpu_log_fn(g, " ");
1024
1025 memset(&rpc, 0, sizeof(struct nv_pmu_rpc_struct_board_obj_grp_cmd));
1026
1027 rpc.class_id = pboardobjgrp->pmu.classid;
1028 rpc.command_id = copy_out ?
1029 NV_PMU_BOARDOBJGRP_CMD_GET_STATUS :
1030 NV_PMU_BOARDOBJGRP_CMD_SET;
1031
1032 rpc.hdr.unit_id = pboardobjgrp->pmu.unitid;
1033 rpc.hdr.function = pboardobjgrp->pmu.rpc_func_id;
1034 rpc.hdr.flags = 0x0;
1035
1036 status = nvgpu_pmu_rpc_execute(pmu, &(rpc.hdr),
1037 (sizeof(rpc) - sizeof(rpc.scratch)),
1038 pcmd->dmem_buffer_size,
1039 NULL, NULL, copy_out);
1040
1041 if (status) {
1042 nvgpu_err(g, "Failed to execute RPC, status=0x%x", status);
1043 }
1044
1045 return status;
1046}