Files
linux-nvgpu/drivers/gpu/nvgpu/common/boardobj/boardobjgrp.c
Nicolas Benech cb2a05dd92 gpu: nvgpu: Fix LibC MISRA 17.7 in common
MISRA Rule-17.7 requires the return value of all functions to be used.
Fix is either to use the return value or change the function to return
void. This patch contains fix for all 17.7 violations instandard C functions
in common code.

JIRA NVGPU-1036

Change-Id: Id6dea92df371e71b22b54cd7a521fc22812f9b69
Signed-off-by: Nicolas Benech <nbenech@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1929899
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2018-11-01 17:15:37 -07:00

1048 lines
26 KiB
C

/*
* Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <nvgpu/bug.h>
#include <nvgpu/gk20a.h>
#include <nvgpu/boardobjgrp.h>
#include <nvgpu/boardobj.h>
#include "ctrl/ctrlboardobj.h"
static boardobjgrp_objinsert boardobjgrp_objinsert_final;
static boardobjgrp_objgetbyidx boardobjgrp_objgetbyidx_final;
static boardobjgrp_objgetnext boardobjgrp_objgetnext_final;
static boardobjgrp_objremoveanddestroy boardobjgrp_objremoveanddestroy_final;
static boardobjgrp_pmudatainstget boardobjgrp_pmudatainstget_stub;
static boardobjgrp_pmustatusinstget boardobjgrp_pmustatusinstget_stub;
static int boardobjgrp_pmucmdsend(struct gk20a *g,
struct boardobjgrp *pboardobjgrp,
struct boardobjgrp_pmu_cmd *pcmd);
static int boardobjgrp_pmucmdsend_rpc(struct gk20a *g,
struct boardobjgrp *pboardobjgrp,
struct boardobjgrp_pmu_cmd *pcmd,
bool copy_out);
struct boardobjgrp_pmucmdhandler_params {
/* Pointer to the BOARDOBJGRP associated with this CMD */
struct boardobjgrp *pboardobjgrp;
/* Pointer to structure representing this NV_PMU_BOARDOBJ_CMD_GRP */
struct boardobjgrp_pmu_cmd *pcmd;
/* Boolean indicating whether the PMU successfully handled the CMD */
u32 success;
};
int boardobjgrp_construct_super(struct gk20a *g,
struct boardobjgrp *pboardobjgrp)
{
nvgpu_log_info(g, " ");
if (pboardobjgrp == NULL) {
return -EINVAL;
}
if (pboardobjgrp->ppobjects == NULL) {
return -EINVAL;
}
if (pboardobjgrp->mask == NULL) {
return -EINVAL;
}
pboardobjgrp->g = g;
pboardobjgrp->objmask = 0;
pboardobjgrp->classid = 0;
pboardobjgrp->pmu.unitid = BOARDOBJGRP_UNIT_ID_INVALID;
pboardobjgrp->pmu.classid = BOARDOBJGRP_GRP_CLASS_ID_INVALID;
pboardobjgrp->pmu.bset = false;
pboardobjgrp->pmu.rpc_func_id = BOARDOBJGRP_GRP_RPC_FUNC_ID_INVALID;
pboardobjgrp->pmu.set.id = BOARDOBJGRP_GRP_CMD_ID_INVALID;
pboardobjgrp->pmu.getstatus.id = BOARDOBJGRP_GRP_CMD_ID_INVALID;
/* Initialize basic interfaces */
pboardobjgrp->destruct = boardobjgrp_destruct_super;
pboardobjgrp->objinsert = boardobjgrp_objinsert_final;
pboardobjgrp->objgetbyidx = boardobjgrp_objgetbyidx_final;
pboardobjgrp->objgetnext = boardobjgrp_objgetnext_final;
pboardobjgrp->objremoveanddestroy =
boardobjgrp_objremoveanddestroy_final;
pboardobjgrp->pmuinithandle = boardobjgrp_pmuinithandle_impl;
pboardobjgrp->pmuhdrdatainit = boardobjgrp_pmuhdrdatainit_super;
pboardobjgrp->pmudatainit = boardobjgrp_pmudatainit_super;
pboardobjgrp->pmuset =
g->ops.pmu_ver.boardobj.boardobjgrp_pmuset_impl;
pboardobjgrp->pmugetstatus =
g->ops.pmu_ver.boardobj.boardobjgrp_pmugetstatus_impl;
pboardobjgrp->pmudatainstget = boardobjgrp_pmudatainstget_stub;
pboardobjgrp->pmustatusinstget = boardobjgrp_pmustatusinstget_stub;
pboardobjgrp->objmaxidx = CTRL_BOARDOBJ_IDX_INVALID;
pboardobjgrp->bconstructed = true;
nvgpu_list_add(&pboardobjgrp->node, &g->boardobjgrp_head);
return 0;
}
int boardobjgrp_destruct_impl(struct boardobjgrp *pboardobjgrp)
{
struct gk20a *g = pboardobjgrp->g;
nvgpu_log_info(g, " ");
if (pboardobjgrp == NULL) {
return -EINVAL;
}
if (!pboardobjgrp->bconstructed) {
return 0;
}
return pboardobjgrp->destruct(pboardobjgrp);
}
int boardobjgrp_destruct_super(struct boardobjgrp *pboardobjgrp)
{
struct boardobj *pboardobj;
struct gk20a *g = pboardobjgrp->g;
int status = 0;
int stat;
u8 index;
nvgpu_log_info(g, " ");
if (pboardobjgrp->mask == NULL) {
return -EINVAL;
}
if (pboardobjgrp->ppobjects == NULL) {
return -EINVAL;
}
BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) {
stat = pboardobjgrp->objremoveanddestroy(pboardobjgrp, index);
if (status == 0) {
status = stat;
}
pboardobjgrp->ppobjects[index] = NULL;
pboardobjgrp->objmask &= ~BIT(index);
}
pboardobjgrp->objmask = 0;
if (pboardobjgrp->objmaxidx != CTRL_BOARDOBJ_IDX_INVALID) {
if (status == 0) {
status = -EINVAL;
}
WARN_ON(true);
}
/* Destroy the PMU CMD data */
stat = boardobjgrp_pmucmd_destroy_impl(g, &pboardobjgrp->pmu.set);
if (status == 0) {
status = stat;
}
stat = boardobjgrp_pmucmd_destroy_impl(g, &pboardobjgrp->pmu.getstatus);
if (status == 0) {
status = stat;
}
nvgpu_list_del(&pboardobjgrp->node);
pboardobjgrp->bconstructed = false;
return status;
}
int boardobjgrp_pmucmd_construct_impl(struct gk20a *g, struct boardobjgrp
*pboardobjgrp, struct boardobjgrp_pmu_cmd *cmd, u8 id, u8 msgid,
u16 hdrsize, u16 entrysize, u16 fbsize, u32 ss_offset, u8 rpc_func_id)
{
nvgpu_log_info(g, " ");
/* Copy the parameters into the CMD*/
cmd->id = id;
cmd->msgid = msgid;
cmd->hdrsize = (u8) hdrsize;
cmd->entrysize = (u8) entrysize;
cmd->fbsize = fbsize;
return 0;
}
int boardobjgrp_pmucmd_construct_impl_v1(struct gk20a *g, struct boardobjgrp
*pboardobjgrp, struct boardobjgrp_pmu_cmd *cmd, u8 id, u8 msgid,
u16 hdrsize, u16 entrysize, u16 fbsize, u32 ss_offset, u8 rpc_func_id)
{
nvgpu_log_fn(g, " ");
/* Copy the parameters into the CMD*/
cmd->dmem_buffer_size = ((hdrsize > entrysize) ? hdrsize : entrysize);
cmd->super_surface_offset = ss_offset;
pboardobjgrp->pmu.rpc_func_id = rpc_func_id;
cmd->fbsize = fbsize;
nvgpu_log_fn(g, "DONE");
return 0;
}
int boardobjgrp_pmucmd_destroy_impl(struct gk20a *g,
struct boardobjgrp_pmu_cmd *cmd)
{
struct nvgpu_mem *mem = &cmd->surf.sysmem_desc;
nvgpu_pmu_surface_free(g, mem);
return 0;
}
int is_boardobjgrp_pmucmd_id_valid_v0(struct gk20a *g,
struct boardobjgrp *pboardobjgrp,
struct boardobjgrp_pmu_cmd *pcmd)
{
int err = 0;
if (pcmd->id == BOARDOBJGRP_GRP_CMD_ID_INVALID) {
err = -EINVAL;
}
return err;
}
int is_boardobjgrp_pmucmd_id_valid_v1(struct gk20a *g,
struct boardobjgrp *pboardobjgrp,
struct boardobjgrp_pmu_cmd *cmd)
{
int err = 0;
if (pboardobjgrp->pmu.rpc_func_id ==
BOARDOBJGRP_GRP_RPC_FUNC_ID_INVALID) {
err = -EINVAL;
}
return err;
}
int boardobjgrp_pmucmd_pmuinithandle_impl(struct gk20a *g,
struct boardobjgrp *pboardobjgrp,
struct boardobjgrp_pmu_cmd *pcmd)
{
int status = 0;
struct nvgpu_mem *sysmem_desc = &pcmd->surf.sysmem_desc;
nvgpu_log_info(g, " ");
if (g->ops.pmu_ver.boardobj.is_boardobjgrp_pmucmd_id_valid(g,
pboardobjgrp, pcmd) != 0) {
goto boardobjgrp_pmucmd_pmuinithandle_exit;
}
if (!pcmd->fbsize) {
goto boardobjgrp_pmucmd_pmuinithandle_exit;
}
nvgpu_pmu_sysmem_surface_alloc(g, sysmem_desc, pcmd->fbsize);
/* we only have got sysmem later this will get copied to vidmem
surface*/
pcmd->surf.vidmem_desc.size = 0;
pcmd->buf = (struct nv_pmu_boardobjgrp_super *)sysmem_desc->cpu_va;
boardobjgrp_pmucmd_pmuinithandle_exit:
return status;
}
int boardobjgrp_pmuinithandle_impl(struct gk20a *g,
struct boardobjgrp *pboardobjgrp)
{
int status = 0;
nvgpu_log_info(g, " ");
status = boardobjgrp_pmucmd_pmuinithandle_impl(g, pboardobjgrp,
&pboardobjgrp->pmu.set);
if (status != 0) {
nvgpu_err(g, "failed to init pmu set cmd");
goto boardobjgrp_pmuinithandle_exit;
}
status = boardobjgrp_pmucmd_pmuinithandle_impl(g, pboardobjgrp,
&pboardobjgrp->pmu.getstatus);
if (status != 0) {
nvgpu_err(g, "failed to init get status command");
goto boardobjgrp_pmuinithandle_exit;
}
/* If the GRP_SET CMD has not been allocated, nothing left to do. */
if ((g->ops.pmu_ver.boardobj.is_boardobjgrp_pmucmd_id_valid(g,
pboardobjgrp, &pboardobjgrp->pmu.set))||
(BOARDOBJGRP_IS_EMPTY(pboardobjgrp))) {
goto boardobjgrp_pmuinithandle_exit;
}
/* Send the BOARDOBJGRP to the pmu via RM_PMU_BOARDOBJ_CMD_GRP. */
status = pboardobjgrp->pmuset(g, pboardobjgrp);
if (status != 0) {
nvgpu_err(g, "failed to send boardobg grp to PMU");
}
boardobjgrp_pmuinithandle_exit:
return status;
}
int boardobjgrp_pmuhdrdatainit_super(struct gk20a *g, struct boardobjgrp
*pboardobjgrp, struct nv_pmu_boardobjgrp_super *pboardobjgrppmu,
struct boardobjgrpmask *mask)
{
nvgpu_log_info(g, " ");
if (pboardobjgrp == NULL) {
return -EINVAL;
}
if (pboardobjgrppmu == NULL) {
return -EINVAL;
}
pboardobjgrppmu->type = pboardobjgrp->type;
pboardobjgrppmu->class_id = pboardobjgrp->classid;
pboardobjgrppmu->obj_slots = BOARDOBJGRP_PMU_SLOTS_GET(pboardobjgrp);
pboardobjgrppmu->flags = 0;
nvgpu_log_info(g, " Done");
return 0;
}
static int boardobjgrp_pmudatainstget_stub(struct gk20a *g,
struct nv_pmu_boardobjgrp *boardobjgrppmu,
struct nv_pmu_boardobj **ppboardobjpmudata, u8 idx)
{
nvgpu_log_info(g, " ");
return -EINVAL;
}
static int boardobjgrp_pmustatusinstget_stub(struct gk20a *g,
void *pboardobjgrppmu,
struct nv_pmu_boardobj_query **ppBoardobjpmustatus, u8 idx)
{
nvgpu_log_info(g, " ");
return -EINVAL;
}
int boardobjgrp_pmudatainit_legacy(struct gk20a *g,
struct boardobjgrp *pboardobjgrp,
struct nv_pmu_boardobjgrp_super *pboardobjgrppmu)
{
int status = 0;
struct boardobj *pboardobj = NULL;
struct nv_pmu_boardobj *ppmudata = NULL;
u8 index;
nvgpu_log_info(g, " ");
if (pboardobjgrp == NULL) {
return -EINVAL;
}
if (pboardobjgrppmu == NULL) {
return -EINVAL;
}
boardobjgrpe32hdrset((struct nv_pmu_boardobjgrp *)pboardobjgrppmu,
pboardobjgrp->objmask);
BOARDOBJGRP_FOR_EACH_INDEX_IN_MASK(32, index, pboardobjgrp->objmask) {
/* Obtain pointer to the current instance of the Object from the Group */
pboardobj = pboardobjgrp->objgetbyidx(pboardobjgrp, index);
if (NULL == pboardobj) {
nvgpu_err(g, "could not get object instance");
status = -EINVAL;
goto boardobjgrppmudatainit_legacy_done;
}
status = pboardobjgrp->pmudatainstget(g,
(struct nv_pmu_boardobjgrp *)pboardobjgrppmu,
&ppmudata, index);
if (status != 0) {
nvgpu_err(g, "could not get object instance");
goto boardobjgrppmudatainit_legacy_done;
}
/* Initialize the PMU Data */
status = pboardobj->pmudatainit(g, pboardobj, ppmudata);
if (status != 0) {
nvgpu_err(g,
"could not parse pmu for device %d", index);
goto boardobjgrppmudatainit_legacy_done;
}
}
BOARDOBJGRP_FOR_EACH_INDEX_IN_MASK_END
boardobjgrppmudatainit_legacy_done:
nvgpu_log_info(g, " Done");
return status;
}
int boardobjgrp_pmudatainit_super(struct gk20a *g, struct boardobjgrp
*pboardobjgrp, struct nv_pmu_boardobjgrp_super *pboardobjgrppmu)
{
int status = 0;
struct boardobj *pboardobj = NULL;
struct nv_pmu_boardobj *ppmudata = NULL;
u8 index;
nvgpu_log_info(g, " ");
if (pboardobjgrp == NULL) {
return -EINVAL;
}
if (pboardobjgrppmu == NULL) {
return -EINVAL;
}
/* Initialize the PMU HDR data.*/
status = pboardobjgrp->pmuhdrdatainit(g, pboardobjgrp, pboardobjgrppmu,
pboardobjgrp->mask);
if (status != 0) {
nvgpu_err(g, "unable to init boardobjgrp pmuhdr data");
goto boardobjgrppmudatainit_super_done;
}
BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct boardobj*, pboardobj, index) {
status = pboardobjgrp->pmudatainstget(g,
(struct nv_pmu_boardobjgrp *)pboardobjgrppmu,
&ppmudata, index);
if (status != 0) {
nvgpu_err(g, "could not get object instance");
goto boardobjgrppmudatainit_super_done;
}
/* Initialize the PMU Data and send to PMU */
status = pboardobj->pmudatainit(g, pboardobj, ppmudata);
if (status != 0) {
nvgpu_err(g,
"could not parse pmu for device %d", index);
goto boardobjgrppmudatainit_super_done;
}
}
boardobjgrppmudatainit_super_done:
nvgpu_log_info(g, " Done");
return status;
}
static int check_boardobjgrp_param(struct gk20a *g,
struct boardobjgrp *pboardobjgrp)
{
if (pboardobjgrp == NULL) {
return -EINVAL;
}
if (!pboardobjgrp->bconstructed) {
return -EINVAL;
}
if (pboardobjgrp->pmu.unitid == BOARDOBJGRP_UNIT_ID_INVALID) {
return -EINVAL;
}
if (pboardobjgrp->pmu.classid == BOARDOBJGRP_GRP_CLASS_ID_INVALID) {
return -EINVAL;
}
/* If no objects in the group, return early */
if (BOARDOBJGRP_IS_EMPTY(pboardobjgrp)) {
return -EINVAL;
}
return 0;
}
int boardobjgrp_pmuset_impl(struct gk20a *g, struct boardobjgrp *pboardobjgrp)
{
int status = 0;
struct boardobjgrp_pmu_cmd *pcmd =
(struct boardobjgrp_pmu_cmd *)(&pboardobjgrp->pmu.set);
nvgpu_log_info(g, " ");
if (check_boardobjgrp_param(g, pboardobjgrp)) {
return -EINVAL;
}
if (pboardobjgrp->pmu.set.id == BOARDOBJGRP_GRP_CMD_ID_INVALID) {
return -EINVAL;
}
if ((pcmd->hdrsize == 0U) ||
(pcmd->entrysize == 0U) ||
(pcmd->buf == NULL)) {
return -EINVAL;
}
/* Initialize PMU buffer with BOARDOBJGRP data. */
(void) memset(pcmd->buf, 0x0, pcmd->fbsize);
status = pboardobjgrp->pmudatainit(g, pboardobjgrp,
pcmd->buf);
if (status != 0) {
nvgpu_err(g, "could not parse pmu data");
goto boardobjgrp_pmuset_exit;
}
/*
* Reset the boolean that indicates set status for most recent
* instance of BOARDOBJGRP.
*/
pboardobjgrp->pmu.bset = false;
/*
* alloc mem in vidmem & copy constructed pmu boardobjgrp data from
* sysmem to vidmem
*/
if (pcmd->surf.vidmem_desc.size == 0U) {
nvgpu_pmu_vidmem_surface_alloc(g, &pcmd->surf.vidmem_desc,
pcmd->fbsize);
}
nvgpu_mem_wr_n(g, &pcmd->surf.vidmem_desc, 0, pcmd->buf, pcmd->fbsize);
/* Send the SET PMU CMD to the PMU */
status = boardobjgrp_pmucmdsend(g, pboardobjgrp,
pcmd);
if (status != 0) {
nvgpu_err(g, "could not send SET CMD to PMU");
goto boardobjgrp_pmuset_exit;
}
pboardobjgrp->pmu.bset = true;
boardobjgrp_pmuset_exit:
return status;
}
int boardobjgrp_pmuset_impl_v1(struct gk20a *g,
struct boardobjgrp *pboardobjgrp)
{
struct nvgpu_pmu *pmu = &g->pmu;
int status = 0;
struct boardobjgrp_pmu_cmd *pcmd =
(struct boardobjgrp_pmu_cmd *)(&pboardobjgrp->pmu.set);
nvgpu_log_info(g, " ");
if (check_boardobjgrp_param(g, pboardobjgrp)) {
return -EINVAL;
}
if ((pcmd->buf == NULL) &&
(pboardobjgrp->pmu.rpc_func_id ==
BOARDOBJGRP_GRP_RPC_FUNC_ID_INVALID)) {
return -EINVAL;
}
/* Initialize PMU buffer with BOARDOBJGRP data. */
(void) memset(pcmd->buf, 0x0, pcmd->fbsize);
status = pboardobjgrp->pmudatainit(g, pboardobjgrp,
pcmd->buf);
if (status != 0) {
nvgpu_err(g, "could not parse pmu data");
goto boardobjgrp_pmuset_exit;
}
/*
* Reset the boolean that indicates set status
* for most recent instance of BOARDOBJGRP.
*/
pboardobjgrp->pmu.bset = false;
/*
* copy constructed pmu boardobjgrp data from
* sysmem to pmu super surface present in FB
*/
nvgpu_mem_wr_n(g, &pmu->super_surface_buf,
pcmd->super_surface_offset, pcmd->buf,
pcmd->fbsize);
/* Send the SET PMU CMD to the PMU using RPC*/
status = boardobjgrp_pmucmdsend_rpc(g, pboardobjgrp,
pcmd, false);
if (status != 0) {
nvgpu_err(g, "could not send SET CMD to PMU");
goto boardobjgrp_pmuset_exit;
}
pboardobjgrp->pmu.bset = true;
boardobjgrp_pmuset_exit:
return status;
}
int
boardobjgrp_pmugetstatus_impl(struct gk20a *g, struct boardobjgrp *pboardobjgrp,
struct boardobjgrpmask *mask)
{
int status = 0;
struct boardobjgrp_pmu_cmd *pcmd =
(struct boardobjgrp_pmu_cmd *)(&pboardobjgrp->pmu.getstatus);
struct boardobjgrp_pmu_cmd *pset =
(struct boardobjgrp_pmu_cmd *)(&pboardobjgrp->pmu.set);
nvgpu_log_info(g, " ");
if (check_boardobjgrp_param(g, pboardobjgrp)) {
return -EINVAL;
}
if (pset->id == BOARDOBJGRP_GRP_CMD_ID_INVALID) {
return -EINVAL;
}
if ((pcmd->hdrsize == 0U) ||
(pcmd->entrysize == 0U) ||
(pcmd->buf == NULL)) {
return -EINVAL;
}
/*
* Can only GET_STATUS if the BOARDOBJGRP has been previously SET to the
* PMU
*/
if (!pboardobjgrp->pmu.bset) {
return -EINVAL;
}
/*
* alloc mem in vidmem & copy constructed pmu boardobjgrp data from
* sysmem to vidmem
*/
if (pcmd->surf.vidmem_desc.size == 0U) {
nvgpu_pmu_vidmem_surface_alloc(g, &pcmd->surf.vidmem_desc,
pcmd->fbsize);
}
/*
* Initialize PMU buffer with the mask of BOARDOBJGRPs for which to
* retrieve status
*/
(void) memset(pcmd->buf, 0x0, pcmd->fbsize);
status = pboardobjgrp->pmuhdrdatainit(g, pboardobjgrp,
pcmd->buf, mask);
if (status != 0) {
nvgpu_err(g, "could not init PMU HDR data");
goto boardobjgrp_pmugetstatus_exit;
}
nvgpu_mem_wr_n(g, &pcmd->surf.vidmem_desc, 0, pset->buf, pset->hdrsize);
/* Send the GET_STATUS PMU CMD to the PMU */
status = boardobjgrp_pmucmdsend(g, pboardobjgrp,
&pboardobjgrp->pmu.getstatus);
if (status != 0) {
nvgpu_err(g, "could not send GET_STATUS cmd to PMU");
goto boardobjgrp_pmugetstatus_exit;
}
/*copy the data back to sysmem buffer that belongs to command*/
nvgpu_mem_rd_n(g, &pcmd->surf.vidmem_desc, 0, pcmd->buf, pcmd->fbsize);
boardobjgrp_pmugetstatus_exit:
return status;
}
int
boardobjgrp_pmugetstatus_impl_v1(struct gk20a *g, struct boardobjgrp *pboardobjgrp,
struct boardobjgrpmask *mask)
{
struct nvgpu_pmu *pmu = &g->pmu;
int status = 0;
struct boardobjgrp_pmu_cmd *pcmd =
(struct boardobjgrp_pmu_cmd *)(&pboardobjgrp->pmu.getstatus);
nvgpu_log_info(g, " ");
if (check_boardobjgrp_param(g, pboardobjgrp)) {
return -EINVAL;
}
if ((pcmd->buf == NULL) &&
(pboardobjgrp->pmu.rpc_func_id ==
BOARDOBJGRP_GRP_RPC_FUNC_ID_INVALID)) {
return -EINVAL;
}
/*
* Can only GET_STATUS if the BOARDOBJGRP has been
* previously SET to the PMU
*/
if (!pboardobjgrp->pmu.bset) {
return -EINVAL;
}
/*
* Initialize PMU buffer with the mask of
* BOARDOBJGRPs for which to retrieve status
*/
(void) memset(pcmd->buf, 0x0, pcmd->fbsize);
status = pboardobjgrp->pmuhdrdatainit(g, pboardobjgrp,
pcmd->buf, mask);
if (status != 0) {
nvgpu_err(g, "could not init PMU HDR data");
goto boardobjgrp_pmugetstatus_exit;
}
/*
* copy constructed pmu boardobjgrp data from
* sysmem to pmu super surface present in FB
*/
nvgpu_mem_wr_n(g, &pmu->super_surface_buf, pcmd->super_surface_offset,
pcmd->buf, pcmd->fbsize);
/* Send the GET_STATUS PMU CMD to the PMU */
status = boardobjgrp_pmucmdsend_rpc(g, pboardobjgrp,
pcmd, true);
if (status != 0) {
nvgpu_err(g, "could not send GET_STATUS cmd to PMU");
goto boardobjgrp_pmugetstatus_exit;
}
/*copy the data back to sysmem buffer that belongs to command*/
nvgpu_mem_rd_n(g, &pmu->super_surface_buf,pcmd->super_surface_offset,
pcmd->buf, pcmd->fbsize);
boardobjgrp_pmugetstatus_exit:
return status;
}
static int
boardobjgrp_objinsert_final(struct boardobjgrp *pboardobjgrp,
struct boardobj *pboardobj, u8 index)
{
struct gk20a *g = pboardobjgrp->g;
nvgpu_log_info(g, " ");
if (pboardobjgrp == NULL) {
return -EINVAL;
}
if (pboardobj == NULL) {
return -EINVAL;
}
if (index > pboardobjgrp->objslots) {
return -EINVAL;
}
if (pboardobjgrp->ppobjects[index] != NULL) {
return -EINVAL;
}
/*
* Check that this BOARDOBJ has not already been added to a
* BOARDOBJGRP
*/
if (pboardobj->idx != CTRL_BOARDOBJ_IDX_INVALID) {
return -EINVAL;
}
pboardobjgrp->ppobjects[index] = pboardobj;
pboardobjgrp->objmaxidx = (u8)(BOARDOBJGRP_IS_EMPTY(pboardobjgrp) ?
index : max(pboardobjgrp->objmaxidx, index));
pboardobj->idx = index;
pboardobjgrp->objmask |= BIT(index);
nvgpu_log_info(g, " Done");
return boardobjgrpmask_bitset(pboardobjgrp->mask, index);
}
static struct boardobj *boardobjgrp_objgetbyidx_final(
struct boardobjgrp *pboardobjgrp, u8 index)
{
if (!boardobjgrp_idxisvalid(pboardobjgrp, index)) {
return NULL;
}
return pboardobjgrp->ppobjects[index];
}
static struct boardobj *boardobjgrp_objgetnext_final(
struct boardobjgrp *pboardobjgrp, u8 *currentindex,
struct boardobjgrpmask *mask)
{
struct boardobj *pboardobjnext = NULL;
u8 objmaxidx;
u8 index;
if (currentindex == NULL) {
return NULL;
}
if (pboardobjgrp == NULL) {
return NULL;
}
/* Search from next element unless first object was requested */
index = (*currentindex != CTRL_BOARDOBJ_IDX_INVALID) ?
(*currentindex + 1U) : 0U;
/* For the cases below in which we have to return NULL */
*currentindex = CTRL_BOARDOBJ_IDX_INVALID;
/* Validate provided mask */
if (mask != NULL) {
if (!(boardobjgrpmask_sizeeq(pboardobjgrp->mask, mask))) {
return NULL;
}
}
objmaxidx = pboardobjgrp->objmaxidx;
if (objmaxidx != CTRL_BOARDOBJ_IDX_INVALID) {
for (; index <= objmaxidx; index++) {
pboardobjnext = pboardobjgrp->ppobjects[index];
if (pboardobjnext != NULL) {
/* Filter results using client provided mask.*/
if (mask != NULL) {
if (!boardobjgrpmask_bitget(mask,
index)) {
pboardobjnext = NULL;
continue;
}
}
*currentindex = index;
break;
}
}
}
return pboardobjnext;
}
static int boardobjgrp_objremoveanddestroy_final(
struct boardobjgrp *pboardobjgrp,
u8 index)
{
int status = 0;
int stat;
struct gk20a *g = pboardobjgrp->g;
nvgpu_log_info(g, " ");
if (!boardobjgrp_idxisvalid(pboardobjgrp, index)) {
return -EINVAL;
}
if (pboardobjgrp->objmaxidx == CTRL_BOARDOBJ_IDX_INVALID) {
return -EINVAL;
}
status = pboardobjgrp->ppobjects[index]->destruct(
pboardobjgrp->ppobjects[index]);
pboardobjgrp->ppobjects[index] = NULL;
pboardobjgrp->objmask &= ~BIT(index);
stat = boardobjgrpmask_bitclr(pboardobjgrp->mask, index);
if (stat) {
if (status == 0) {
status = stat;
}
}
/* objmaxidx requires update only if that very object was removed */
if (pboardobjgrp->objmaxidx == index) {
pboardobjgrp->objmaxidx =
boardobjgrpmask_bitidxhighest(pboardobjgrp->mask);
}
return status;
}
void boardobjgrpe32hdrset(struct nv_pmu_boardobjgrp *hdr, u32 objmask)
{
u32 slots = objmask;
HIGHESTBITIDX_32(slots);
slots++;
hdr->super.type = CTRL_BOARDOBJGRP_TYPE_E32;
hdr->super.class_id = 0;
hdr->super.obj_slots = (u8)slots;
hdr->obj_mask = objmask;
}
static void boardobjgrp_pmucmdhandler(struct gk20a *g, struct pmu_msg *msg,
void *param, u32 handle, u32 status)
{
struct nv_pmu_boardobj_msg_grp *pgrpmsg;
struct boardobjgrp_pmucmdhandler_params *phandlerparams =
(struct boardobjgrp_pmucmdhandler_params *)param;
struct boardobjgrp *pboardobjgrp = phandlerparams->pboardobjgrp;
struct boardobjgrp_pmu_cmd *pgrpcmd = phandlerparams->pcmd;
nvgpu_log_info(g, " ");
pgrpmsg = &msg->msg.boardobj.grp;
if (pgrpmsg->class_id != pboardobjgrp->pmu.classid) {
nvgpu_err(g,
"Unrecognized GRP type: unit %x class id=0x%02x cmd id %x",
msg->hdr.unit_id, pboardobjgrp->pmu.classid,
pgrpcmd->id);
return;
}
if (msg->msg.boardobj.msg_type != pgrpcmd->msgid) {
nvgpu_err(g,
"unsupported msg for unit %x class %x cmd id %x msg %x",
msg->hdr.unit_id, pboardobjgrp->pmu.classid,
pgrpcmd->id, msg->msg.boardobj.msg_type);
return;
}
if (msg->msg.boardobj.grp_set.flcn_status != 0U) {
nvgpu_err(g,
"cmd abort for unit %x class %x cmd id %x status %x",
msg->hdr.unit_id, pboardobjgrp->pmu.classid,
pgrpcmd->id,
msg->msg.boardobj.grp_set.flcn_status);
return;
}
phandlerparams->success = pgrpmsg->b_success ? 1 : 0;
if (!pgrpmsg->b_success) {
nvgpu_err(g,
"failed GRPCMD: msgtype=0x%x, classid=0x%x, cmd id %x",
pgrpmsg->msg_type, pgrpmsg->class_id,
pgrpcmd->id);
return;
}
}
static int boardobjgrp_pmucmdsend(struct gk20a *g,
struct boardobjgrp *pboardobjgrp,
struct boardobjgrp_pmu_cmd *pcmd)
{
struct boardobjgrp_pmucmdhandler_params handlerparams;
struct pmu_payload payload;
struct nv_pmu_boardobj_cmd_grp *pgrpcmd;
struct pmu_cmd cmd;
u32 seqdesc;
int status = 0;
nvgpu_log_info(g, " ");
(void) memset(&payload, 0, sizeof(payload));
(void) memset(&handlerparams, 0, sizeof(handlerparams));
(void) memset(&cmd, 0, sizeof(struct pmu_cmd));
cmd.hdr.unit_id = pboardobjgrp->pmu.unitid;
cmd.hdr.size = sizeof(struct nv_pmu_boardobj_cmd_grp) +
sizeof(struct pmu_hdr);
pgrpcmd = &cmd.cmd.boardobj.grp;
pgrpcmd->cmd_type = pcmd->id;
pgrpcmd->class_id = pboardobjgrp->pmu.classid;
pgrpcmd->grp.hdr_size = pcmd->hdrsize;
pgrpcmd->grp.entry_size = pcmd->entrysize;
/*
* copy vidmem information to boardobj_cmd_grp
*/
nvgpu_pmu_surface_describe(g, &pcmd->surf.vidmem_desc,
&pgrpcmd->grp.fb);
/*
* PMU reads command from sysmem so assigned
* "payload.in.buf = pcmd->buf"
* but PMU access pmu boardobjgrp data from vidmem copied above
*/
payload.in.buf = pcmd->buf;
payload.in.size = max(pcmd->hdrsize, pcmd->entrysize);
payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED;
payload.in.offset = offsetof(struct nv_pmu_boardobj_cmd_grp, grp);
/* Setup the handler params to communicate back results.*/
handlerparams.pboardobjgrp = pboardobjgrp;
handlerparams.pcmd = pcmd;
handlerparams.success = 0;
status = nvgpu_pmu_cmd_post(g, &cmd, NULL, &payload,
PMU_COMMAND_QUEUE_LPQ,
boardobjgrp_pmucmdhandler,
(void *)&handlerparams,
&seqdesc, ~0);
if (status != 0) {
nvgpu_err(g,
"unable to post boardobj grp cmd for unit %x cmd id %x",
cmd.hdr.unit_id, pcmd->id);
goto boardobjgrp_pmucmdsend_exit;
}
pmu_wait_message_cond(&g->pmu,
gk20a_get_gr_idle_timeout(g),
&handlerparams.success, 1);
if (handlerparams.success == 0U) {
nvgpu_err(g, "could not process cmd");
status = -ETIMEDOUT;
goto boardobjgrp_pmucmdsend_exit;
}
boardobjgrp_pmucmdsend_exit:
return status;
}
static int boardobjgrp_pmucmdsend_rpc(struct gk20a *g,
struct boardobjgrp *pboardobjgrp,
struct boardobjgrp_pmu_cmd *pcmd,
bool copy_out)
{
struct nvgpu_pmu *pmu = &g->pmu;
struct nv_pmu_rpc_struct_board_obj_grp_cmd rpc;
int status = 0;
nvgpu_log_fn(g, " ");
(void) memset(&rpc, 0,
sizeof(struct nv_pmu_rpc_struct_board_obj_grp_cmd));
rpc.class_id = pboardobjgrp->pmu.classid;
rpc.command_id = copy_out ?
NV_PMU_BOARDOBJGRP_CMD_GET_STATUS :
NV_PMU_BOARDOBJGRP_CMD_SET;
rpc.hdr.unit_id = pboardobjgrp->pmu.unitid;
rpc.hdr.function = pboardobjgrp->pmu.rpc_func_id;
rpc.hdr.flags = 0x0;
status = nvgpu_pmu_rpc_execute(pmu, &(rpc.hdr),
(sizeof(rpc) - sizeof(rpc.scratch)),
pcmd->dmem_buffer_size,
NULL, NULL, copy_out);
if (status != 0) {
nvgpu_err(g, "Failed to execute RPC, status=0x%x", status);
}
return status;
}