summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/boardobj/boardobjgrp.c
diff options
context:
space:
mode:
authorVijayakumar Subbu <vsubbu@nvidia.com>2016-07-28 01:29:15 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2016-09-29 16:17:46 -0400
commitb17d9708c9e9930778de43de1edf1385acb13ebd (patch)
treefc485e96cc19575d463c61c8b80a09dd89745f3f /drivers/gpu/nvgpu/boardobj/boardobjgrp.c
parent27b47b1969d7d9cdd3de9fd6f0131ad357f4b0fa (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.c697
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
20static boardobjgrp_objinsert boardobjgrp_objinsert_final;
21static boardobjgrp_objgetbyidx boardobjgrp_objgetbyidx_final;
22static boardobjgrp_objgetnext boardobjgrp_objgetnext_final;
23static boardobjgrp_objremoveanddestroy boardobjgrp_objremoveanddestroy_final;
24static boardobjgrp_pmudatainstget boardobjgrp_pmudatainstget_stub;
25static boardobjgrp_pmustatusinstget boardobjgrp_pmustatusinstget_stub;
26static u32 boardobjgrp_pmucmdsend(struct gk20a *g,
27 struct boardobjgrp *pboardobjgrp,
28 struct boardobjgrp_pmu_cmd *pcmd);
29struct 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
38u32 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
82u32 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
95u32 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
141u32 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
158u32 boardobjgrp_pmucmd_destroy_impl(struct boardobjgrp_pmu_cmd *cmd)
159{
160 return 0;
161}
162
163u32 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
179boardobjgrp_pmucmd_pmuinithandle_exit:
180 return status;
181}
182
183u32 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
214boardobjgrp_pmuinithandle_exit:
215 return status;
216}
217
218
219u32 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
237u32 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
246u32 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
254u32 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
297boardobjgrppmudatainit_super_done:
298 gk20a_dbg_info(" Done");
299 return status;
300}
301
302u32 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
358boardobjgrp_pmuset_exit:
359 return status;
360}
361
362u32
363boardobjgrp_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
424boardobjgrp_pmugetstatus_exit:
425 return status;
426}
427
428static u32
429boardobjgrp_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
466static 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
474static 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
525static 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
562void 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
577static 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
626static 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
695boardobjgrp_pmucmdsend_exit:
696 return status;
697}