mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-23 01:50:07 +03:00
The function nvgpu_pmu_cmd_post() included a timeout parameter, but all callers were just passing the max value, so it was useless. This change removes that parameter from that function. The same was true for therm_pmu_cmd_post() that calls nvgpu_pmu_cmd_post(), so do the same to it. JIRA NVGPU-1008 Change-Id: I634ac40104ebd7cce36013a585dcb818aefd546a Signed-off-by: Philip Elcan <pelcan@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1962178 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: svc-misra-checker <svc-misra-checker@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Alex Waterman <alexw@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
1068 lines
27 KiB
C
1068 lines
27 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 <nvgpu/pmuif/ctrlboardobj.h>
|
|
/*
|
|
* Inserts a previously constructed Board Object into a Board Object Group for
|
|
* tracking. Objects are inserted in the array based on the given index.
|
|
*/
|
|
static int boardobjgrp_objinsert_final(struct boardobjgrp *pboardobjgrp,
|
|
struct boardobj *pboardobj, u8 index);
|
|
/*
|
|
* Retrieves a Board Object from a Board Object Group using the group's index.
|
|
*/
|
|
static struct boardobj *boardobjgrp_objgetbyidx_final(
|
|
struct boardobjgrp *pboardobjgrp, u8 index);
|
|
/*
|
|
* Retrieve Board Object immediately following one pointed by @ref currentindex
|
|
* filtered out by the provided mask. If (mask == NULL) => no filtering.
|
|
*/
|
|
static struct boardobj *boardobjgrp_objgetnext_final(
|
|
struct boardobjgrp *pboardobjgrp,
|
|
u8 *currentindex, struct boardobjgrpmask *mask);
|
|
static int boardobjgrp_objremoveanddestroy_final(
|
|
struct boardobjgrp *pboardobjgrp,
|
|
u8 index);
|
|
static int boardobjgrp_pmudatainstget_stub(struct gk20a *g,
|
|
struct nv_pmu_boardobjgrp *boardobjgrppmu,
|
|
struct nv_pmu_boardobj **ppboardobjpmudata, u8 idx);
|
|
static int boardobjgrp_pmustatusinstget_stub(struct gk20a *g,
|
|
void *pboardobjgrppmu,
|
|
struct nv_pmu_boardobj_query **ppBoardobjpmustatus,
|
|
u8 idx);
|
|
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 == 0U) {
|
|
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) != 0)||
|
|
(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) != 0) {
|
|
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) != 0) {
|
|
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) != 0) {
|
|
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) != 0) {
|
|
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 != 0) {
|
|
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);
|
|
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;
|
|
}
|