From 3336131d1702717dbab4753e46f1ffda1ea7b81f Mon Sep 17 00:00:00 2001 From: Divya Date: Thu, 16 Dec 2021 06:52:37 +0000 Subject: [PATCH] gpu: nvgpu: add IDLE_SNAP RPC Add support for IDLE_SNAP RPC sent from PMU. This RPC event is received when ELPG is engaged and some register, which lies in powergated region, is accessed for read/write. This RPC sends information like reason for idle_snap and cached value of idle status registers. JIRA NVGPU-7327 Signed-off-by: Divya Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2642951 (cherry picked from commit 744782e0885cdc64d750783350862c5c5f04854e) Change-Id: I704850f9ccf7c4e0d33f005696b8c275b958ad3e Signed-off-by: Mayur Poojary Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2653435 Reviewed-by: svcacv Reviewed-by: Vijayakumar Subbu GVS: Gerrit_Virtual_Submit Tested-by: Amulya Yarlagadda --- drivers/gpu/nvgpu/common/pmu/pg/pg_sw_ga10b.c | 43 ++++++++++++++++++- drivers/gpu/nvgpu/common/pmu/pg/pg_sw_ga10b.h | 32 +++++++++++++- .../gpu/nvgpu/include/nvgpu/pmu/pmuif/pg.h | 20 +++++++++ 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/nvgpu/common/pmu/pg/pg_sw_ga10b.c b/drivers/gpu/nvgpu/common/pmu/pg/pg_sw_ga10b.c index c0c010947..40ae84340 100644 --- a/drivers/gpu/nvgpu/common/pmu/pg/pg_sw_ga10b.c +++ b/drivers/gpu/nvgpu/common/pmu/pg/pg_sw_ga10b.c @@ -402,21 +402,60 @@ static int ga10b_pmu_pg_handle_async_cmd_resp(struct gk20a *g, u32 ctrl_id, return err; } +static int ga10b_pmu_pg_handle_idle_snap_rpc(struct gk20a *g, + struct pmu_nv_rpc_struct_lpwr_pg_idle_snap *idle_snap_rpc) +{ + int err = 0; + + nvgpu_err(g, "IDLE SNAP RPC received"); + nvgpu_err(g, "IDLE SNAP ctrl_id:%d", idle_snap_rpc->ctrl_id); + nvgpu_err(g, "IDLE SNAP reason:0x%x", idle_snap_rpc->reason); + + switch (idle_snap_rpc->reason) { + case PG_IDLE_SNAP_REASON_ERR_IDLE_FLIP_POWERING_DOWN: + nvgpu_err(g, "IDLE_SNAP reason:ERR_IDLE_FLIP_POWERING_DOWN"); + break; + case PG_IDLE_SNAP_REASON_ERR_IDLE_FLIP_PWR_OFF: + nvgpu_err(g, "IDLE_SNAP reason:ERR_IDLE_PWR_OFF"); + break; + default: + nvgpu_err(g, "IDLE_SNAP reason unknown"); + err = -EINVAL; + break; + } + + nvgpu_err(g, "IDLE SNAP idle_status: 0x%x", + idle_snap_rpc->idle_status); + nvgpu_err(g, "IDLE SNAP idle_status1: 0x%x", + idle_snap_rpc->idle_status1); + nvgpu_err(g, "IDLE SNAP idle_status2: 0x%x", + idle_snap_rpc->idle_status2); + return err; +} + static int ga10b_pmu_pg_process_rpc_event(struct gk20a *g, void *pmumsg) { int err = 0; - struct pmu_rm_rpc_struct_lpwr_pg_async_cmd_resp *async_cmd; + struct pmu_nv_rpc_struct_lpwr_pg_async_cmd_resp *async_cmd; + struct pmu_nv_rpc_struct_lpwr_pg_idle_snap *idle_snap_rpc; struct pmu_nvgpu_rpc_pg_event *msg = (struct pmu_nvgpu_rpc_pg_event *)pmumsg; switch (msg->rpc_hdr.function) { case PMU_NV_RPC_ID_LPWR_PG_ASYNC_CMD_RESP: async_cmd = - (struct pmu_rm_rpc_struct_lpwr_pg_async_cmd_resp *) + (struct pmu_nv_rpc_struct_lpwr_pg_async_cmd_resp *) (void *)(&msg->rpc_hdr); err = ga10b_pmu_pg_handle_async_cmd_resp(g, async_cmd->ctrl_id, async_cmd->msg_id); break; + case PMU_NV_RPC_ID_LPWR_PG_IDLE_SNAP: + idle_snap_rpc = + (struct pmu_nv_rpc_struct_lpwr_pg_idle_snap *) + (void *)(&msg->rpc_hdr); + err = ga10b_pmu_pg_handle_idle_snap_rpc(g, idle_snap_rpc); + break; + default: nvgpu_err(g, "Invalid PMU RPC: 0x%x", msg->rpc_hdr.function); err = -EINVAL; diff --git a/drivers/gpu/nvgpu/common/pmu/pg/pg_sw_ga10b.h b/drivers/gpu/nvgpu/common/pmu/pg/pg_sw_ga10b.h index 66d5449ac..7fd0ec8aa 100644 --- a/drivers/gpu/nvgpu/common/pmu/pg/pg_sw_ga10b.h +++ b/drivers/gpu/nvgpu/common/pmu/pg/pg_sw_ga10b.h @@ -269,7 +269,7 @@ struct pmu_rpc_struct_lpwr_loading_pg_ctrl_buf_load /*! * Defines the structure that holds data used to execute PG_ASYNC_CMD_RESP RPC. */ -struct pmu_rm_rpc_struct_lpwr_pg_async_cmd_resp { +struct pmu_nv_rpc_struct_lpwr_pg_async_cmd_resp { /*! * Must be first field in RPC structure. */ @@ -284,6 +284,36 @@ struct pmu_rm_rpc_struct_lpwr_pg_async_cmd_resp { u8 msg_id; }; +/*! + * Defines the structure that holds data used to execute PG_IDLE_SNAP RPC. + */ +struct pmu_nv_rpc_struct_lpwr_pg_idle_snap { + /*! + * Must be first field in RPC structure. + */ + struct nv_pmu_rpc_header hdr; + /*! + * PgCtrl ID. + */ + u8 ctrl_id; + /*! + * Idle Snap reason. + */ + u8 reason; + /*! + * Primary status from Idle Snap. + */ + u32 idle_status; + /*! + * Additional status from Idle Snap. + */ + u32 idle_status1; + /*! + * Additional status from Idle Snap. + */ + u32 idle_status2; +}; + /* * Brief Statistics structure for PG features */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmu/pmuif/pg.h b/drivers/gpu/nvgpu/include/nvgpu/pmu/pmuif/pg.h index 75105e3fc..618ccf256 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmu/pmuif/pg.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmu/pmuif/pg.h @@ -52,6 +52,26 @@ #define PMU_NV_RPC_ID_LPWR_PG_LOG_FLUSHED 0x01U #define PMU_NV_RPC_ID_LPWR_PG_IDLE_SNAP 0x02U +/*! + * @brief Idle snap reason + * + * Idle snap representing errors: + * PMU ucode converts idle snap interrupt to DISALLOW event and disables + * PgCtrl forever. + * + * ERR_IDLE_FLIP_POWERING_DOWN : Idle signal reported busy in POWERING_DOWN + * state. This means idle-flip was asserted + * after point of no-return. + * ERR_IDLE_FLIP_PWR_OFF : Idle signal reported busy in PWR_OFF state. + * It was not expected to change the state of + * signal in PWR_OFF state. + * ERR_UNKNOWN : PMU ucode is not able to find the valid + * reason for idle snap. + */ +#define PG_IDLE_SNAP_REASON_ERR_IDLE_FLIP_POWERING_DOWN BIT(0) +#define PG_IDLE_SNAP_REASON_ERR_IDLE_FLIP_PWR_OFF BIT(1) +#define PG_IDLE_SNAP_REASON_ERR_UNKNOWN BIT(2) + /* Async PG message IDs */ enum { PMU_PG_MSG_ASYNC_CMD_DISALLOW,