1*90eb1077SAndy Ritger /* 2*90eb1077SAndy Ritger * SPDX-FileCopyrightText: Copyright (c) 2021-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3*90eb1077SAndy Ritger * SPDX-License-Identifier: MIT 4*90eb1077SAndy Ritger * 5*90eb1077SAndy Ritger * Permission is hereby granted, free of charge, to any person obtaining a 6*90eb1077SAndy Ritger * copy of this software and associated documentation files (the "Software"), 7*90eb1077SAndy Ritger * to deal in the Software without restriction, including without limitation 8*90eb1077SAndy Ritger * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9*90eb1077SAndy Ritger * and/or sell copies of the Software, and to permit persons to whom the 10*90eb1077SAndy Ritger * Software is furnished to do so, subject to the following conditions: 11*90eb1077SAndy Ritger * 12*90eb1077SAndy Ritger * The above copyright notice and this permission notice shall be included in 13*90eb1077SAndy Ritger * all copies or substantial portions of the Software. 14*90eb1077SAndy Ritger * 15*90eb1077SAndy Ritger * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16*90eb1077SAndy Ritger * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*90eb1077SAndy Ritger * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18*90eb1077SAndy Ritger * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19*90eb1077SAndy Ritger * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20*90eb1077SAndy Ritger * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21*90eb1077SAndy Ritger * DEALINGS IN THE SOFTWARE. 22*90eb1077SAndy Ritger */ 23*90eb1077SAndy Ritger 24*90eb1077SAndy Ritger /*! 25*90eb1077SAndy Ritger * 26*90eb1077SAndy Ritger * @file kern_fsp.c 27*90eb1077SAndy Ritger * @brief Provides all kernel side interfaces for tracking the FSP state, 28*90eb1077SAndy Ritger * submitting commands and parsing replies needed from the CPU. 29*90eb1077SAndy Ritger */ 30*90eb1077SAndy Ritger #include "gpu/gpu.h" 31*90eb1077SAndy Ritger #include "gpu/fsp/kern_fsp.h" 32*90eb1077SAndy Ritger #include "nvrm_registry.h" 33*90eb1077SAndy Ritger 34*90eb1077SAndy Ritger #if RMCFG_MODULE_ENABLED (GSP) 35*90eb1077SAndy Ritger #include "gpu/gsp/gsp.h" 36*90eb1077SAndy Ritger #include "objflcnable.h" 37*90eb1077SAndy Ritger #endif 38*90eb1077SAndy Ritger 39*90eb1077SAndy Ritger /*! 40*90eb1077SAndy Ritger * Local object related functions 41*90eb1077SAndy Ritger */ 42*90eb1077SAndy Ritger static void kfspInitRegistryOverrides(OBJGPU *, KernelFsp *); 43*90eb1077SAndy Ritger 44*90eb1077SAndy Ritger static NV_STATUS kfspReadMessage(OBJGPU *pGpu, KernelFsp *pKernelFsp, NvU8 *pPayloadBuffer, NvU32 payloadBufferSize); 45*90eb1077SAndy Ritger 46*90eb1077SAndy Ritger NV_STATUS 47*90eb1077SAndy Ritger kfspConstructEngine_IMPL(OBJGPU *pGpu, KernelFsp *pKernelFsp, ENGDESCRIPTOR engDesc) 48*90eb1077SAndy Ritger { 49*90eb1077SAndy Ritger 50*90eb1077SAndy Ritger // Initialize based on registry keys 51*90eb1077SAndy Ritger kfspInitRegistryOverrides(pGpu, pKernelFsp); 52*90eb1077SAndy Ritger if (pKernelFsp->getProperty(pKernelFsp, PDB_PROP_KFSP_IS_MISSING)) 53*90eb1077SAndy Ritger { 54*90eb1077SAndy Ritger NV_PRINTF(LEVEL_WARNING, "KernelFsp is disabled\n"); 55*90eb1077SAndy Ritger return NV_ERR_OBJECT_NOT_FOUND; 56*90eb1077SAndy Ritger } 57*90eb1077SAndy Ritger return NV_OK; 58*90eb1077SAndy Ritger } 59*90eb1077SAndy Ritger 60*90eb1077SAndy Ritger /*! 61*90eb1077SAndy Ritger * Initialize all registry overrides for this object 62*90eb1077SAndy Ritger * 63*90eb1077SAndy Ritger * @param[in] pGpu GPU object pointer 64*90eb1077SAndy Ritger * @param[in] pKernelFsp KernelFsp object pointer 65*90eb1077SAndy Ritger */ 66*90eb1077SAndy Ritger static void 67*90eb1077SAndy Ritger kfspInitRegistryOverrides 68*90eb1077SAndy Ritger ( 69*90eb1077SAndy Ritger OBJGPU *pGpu, 70*90eb1077SAndy Ritger KernelFsp *pKernelFsp 71*90eb1077SAndy Ritger ) 72*90eb1077SAndy Ritger { 73*90eb1077SAndy Ritger NvU32 data = 0; 74*90eb1077SAndy Ritger 75*90eb1077SAndy Ritger if (((osReadRegistryDword(pGpu, NV_REG_STR_RM_DISABLE_FSP, &data) == NV_OK) && 76*90eb1077SAndy Ritger (data == NV_REG_STR_RM_DISABLE_FSP_YES) && IS_EMULATION(pGpu)) || 77*90eb1077SAndy Ritger IS_FMODEL(pGpu)) 78*90eb1077SAndy Ritger { 79*90eb1077SAndy Ritger // 80*90eb1077SAndy Ritger // Force disable FSP engine, used only on emulation because some 81*90eb1077SAndy Ritger // emulation netlists stub out FSP but leave the engine in PTOP 82*90eb1077SAndy Ritger // 83*90eb1077SAndy Ritger NV_PRINTF(LEVEL_WARNING, "FSP disabled due to regkey override.\n"); 84*90eb1077SAndy Ritger pKernelFsp->setProperty(pKernelFsp, PDB_PROP_KFSP_IS_MISSING, NV_TRUE); 85*90eb1077SAndy Ritger } 86*90eb1077SAndy Ritger 87*90eb1077SAndy Ritger if (osReadRegistryDword(pGpu, NV_REG_STR_RM_DISABLE_COT_CMD, &data) == NV_OK) 88*90eb1077SAndy Ritger { 89*90eb1077SAndy Ritger // Assume non-zero value only has NV_REG_STR_RM_DISABLE_COT_CMD_YES 90*90eb1077SAndy Ritger if (data & DRF_SHIFTMASK(NV_REG_STR_RM_DISABLE_COT_CMD_FRTS_SYSMEM)) 91*90eb1077SAndy Ritger { 92*90eb1077SAndy Ritger pKernelFsp->setProperty(pKernelFsp, PDB_PROP_KFSP_DISABLE_FRTS_SYSMEM, NV_TRUE); 93*90eb1077SAndy Ritger } 94*90eb1077SAndy Ritger 95*90eb1077SAndy Ritger if (data & DRF_SHIFTMASK(NV_REG_STR_RM_DISABLE_COT_CMD_FRTS_VIDMEM)) 96*90eb1077SAndy Ritger { 97*90eb1077SAndy Ritger pKernelFsp->setProperty(pKernelFsp, PDB_PROP_KFSP_DISABLE_FRTS_VIDMEM, NV_TRUE); 98*90eb1077SAndy Ritger } 99*90eb1077SAndy Ritger 100*90eb1077SAndy Ritger if (data & DRF_SHIFTMASK(NV_REG_STR_RM_DISABLE_COT_CMD_GSPFMC)) 101*90eb1077SAndy Ritger { 102*90eb1077SAndy Ritger pKernelFsp->setProperty(pKernelFsp, PDB_PROP_KFSP_DISABLE_GSPFMC, NV_TRUE); 103*90eb1077SAndy Ritger } 104*90eb1077SAndy Ritger } 105*90eb1077SAndy Ritger 106*90eb1077SAndy Ritger // Inst-in-sys must only set up FRTS in SYSMEM. This includes FB broken. 107*90eb1077SAndy Ritger if (pGpu->getProperty(pGpu, PDB_PROP_GPU_IS_ALL_INST_IN_SYSMEM)) 108*90eb1077SAndy Ritger { 109*90eb1077SAndy Ritger pKernelFsp->setProperty(pKernelFsp, PDB_PROP_KFSP_DISABLE_FRTS_VIDMEM, NV_TRUE); 110*90eb1077SAndy Ritger } 111*90eb1077SAndy Ritger } 112*90eb1077SAndy Ritger 113*90eb1077SAndy Ritger 114*90eb1077SAndy Ritger /*! 115*90eb1077SAndy Ritger * @brief FSP State Initialization. 116*90eb1077SAndy Ritger * 117*90eb1077SAndy Ritger * Initializes all software states including allocating the dbg memory surface 118*90eb1077SAndy Ritger * and the initialization of FSP HAL layer. 119*90eb1077SAndy Ritger * 120*90eb1077SAndy Ritger * @param[in] pGpu GPU object pointer 121*90eb1077SAndy Ritger * @param[in] pKernelFsp FSP object pointer 122*90eb1077SAndy Ritger * 123*90eb1077SAndy Ritger * @return 'NV_OK' if state-initialization was successful. 124*90eb1077SAndy Ritger * @return other bubbles up errors from @ref kfspStateInitHal_HAL on failure 125*90eb1077SAndy Ritger */ 126*90eb1077SAndy Ritger NV_STATUS 127*90eb1077SAndy Ritger kfspStateInitUnlocked_IMPL 128*90eb1077SAndy Ritger ( 129*90eb1077SAndy Ritger OBJGPU *pGpu, 130*90eb1077SAndy Ritger KernelFsp *pKernelFsp 131*90eb1077SAndy Ritger ) 132*90eb1077SAndy Ritger { 133*90eb1077SAndy Ritger return NV_OK; 134*90eb1077SAndy Ritger } 135*90eb1077SAndy Ritger 136*90eb1077SAndy Ritger /*! 137*90eb1077SAndy Ritger * @brief Destroy FSP state 138*90eb1077SAndy Ritger * 139*90eb1077SAndy Ritger * @param[in] pGpu GPU object pointer 140*90eb1077SAndy Ritger * @param[in] pKernelFsp FSP object pointer 141*90eb1077SAndy Ritger * 142*90eb1077SAndy Ritger * @return 'NV_OK' if the FSP state was successfully destroyed 143*90eb1077SAndy Ritger */ 144*90eb1077SAndy Ritger void 145*90eb1077SAndy Ritger kfspStateDestroy_IMPL 146*90eb1077SAndy Ritger ( 147*90eb1077SAndy Ritger OBJGPU *pGpu, 148*90eb1077SAndy Ritger KernelFsp *pKernelFsp 149*90eb1077SAndy Ritger ) 150*90eb1077SAndy Ritger { 151*90eb1077SAndy Ritger if (pKernelFsp->pCotPayload != NULL) 152*90eb1077SAndy Ritger { 153*90eb1077SAndy Ritger portMemFree(pKernelFsp->pCotPayload); 154*90eb1077SAndy Ritger pKernelFsp->pCotPayload = NULL; 155*90eb1077SAndy Ritger } 156*90eb1077SAndy Ritger 157*90eb1077SAndy Ritger if (pKernelFsp->pSysmemFrtsMemdesc != NULL) 158*90eb1077SAndy Ritger { 159*90eb1077SAndy Ritger memdescUnmap(pKernelFsp->pSysmemFrtsMemdesc, NV_TRUE, 0, 160*90eb1077SAndy Ritger memdescGetKernelMapping(pKernelFsp->pSysmemFrtsMemdesc), 161*90eb1077SAndy Ritger memdescGetKernelMappingPriv(pKernelFsp->pSysmemFrtsMemdesc)); 162*90eb1077SAndy Ritger memdescFree(pKernelFsp->pSysmemFrtsMemdesc); 163*90eb1077SAndy Ritger memdescDestroy(pKernelFsp->pSysmemFrtsMemdesc); 164*90eb1077SAndy Ritger pKernelFsp->pSysmemFrtsMemdesc = NULL; 165*90eb1077SAndy Ritger } 166*90eb1077SAndy Ritger 167*90eb1077SAndy Ritger if (pKernelFsp->pVidmemFrtsMemdesc != NULL) 168*90eb1077SAndy Ritger { 169*90eb1077SAndy Ritger memdescFree(pKernelFsp->pVidmemFrtsMemdesc); 170*90eb1077SAndy Ritger memdescDestroy(pKernelFsp->pVidmemFrtsMemdesc); 171*90eb1077SAndy Ritger pKernelFsp->pVidmemFrtsMemdesc = NULL; 172*90eb1077SAndy Ritger } 173*90eb1077SAndy Ritger 174*90eb1077SAndy Ritger if (pKernelFsp->pGspFmcMemdesc != NULL) 175*90eb1077SAndy Ritger { 176*90eb1077SAndy Ritger memdescFree(pKernelFsp->pGspFmcMemdesc); 177*90eb1077SAndy Ritger memdescDestroy(pKernelFsp->pGspFmcMemdesc); 178*90eb1077SAndy Ritger pKernelFsp->pGspFmcMemdesc = NULL; 179*90eb1077SAndy Ritger } 180*90eb1077SAndy Ritger 181*90eb1077SAndy Ritger if (pKernelFsp->pGspBootArgsMemdesc != NULL) 182*90eb1077SAndy Ritger { 183*90eb1077SAndy Ritger memdescFree(pKernelFsp->pGspBootArgsMemdesc); 184*90eb1077SAndy Ritger memdescDestroy(pKernelFsp->pGspBootArgsMemdesc); 185*90eb1077SAndy Ritger pKernelFsp->pGspBootArgsMemdesc = NULL; 186*90eb1077SAndy Ritger } 187*90eb1077SAndy Ritger 188*90eb1077SAndy Ritger } 189*90eb1077SAndy Ritger 190*90eb1077SAndy Ritger /*! 191*90eb1077SAndy Ritger * @brief Override default behaviour of reset 192*90eb1077SAndy Ritger * 193*90eb1077SAndy Ritger * @param[in] pGpu GPU object pointer 194*90eb1077SAndy Ritger * @param[in] pKernelFsp FSP object pointer 195*90eb1077SAndy Ritger * 196*90eb1077SAndy Ritger * @return 197*90eb1077SAndy Ritger */ 198*90eb1077SAndy Ritger void 199*90eb1077SAndy Ritger kfspSecureReset_IMPL 200*90eb1077SAndy Ritger ( 201*90eb1077SAndy Ritger OBJGPU *pGpu, 202*90eb1077SAndy Ritger KernelFsp *pKernelFsp 203*90eb1077SAndy Ritger ) 204*90eb1077SAndy Ritger { 205*90eb1077SAndy Ritger // Should not reset FSP 206*90eb1077SAndy Ritger NV_PRINTF(LEVEL_ERROR, "FSP cannot be reset by CPU.\n"); 207*90eb1077SAndy Ritger NV_ASSERT(0); 208*90eb1077SAndy Ritger return; 209*90eb1077SAndy Ritger } 210*90eb1077SAndy Ritger 211*90eb1077SAndy Ritger 212*90eb1077SAndy Ritger /*! 213*90eb1077SAndy Ritger * @brief Check if FSP RM command queue is empty 214*90eb1077SAndy Ritger * 215*90eb1077SAndy Ritger * @param[in] pGpu OBJGPU pointer 216*90eb1077SAndy Ritger * @param[in] pKernelFsp KernelFsp pointer 217*90eb1077SAndy Ritger * 218*90eb1077SAndy Ritger * @return NV_TRUE if queue is empty, NV_FALSE otherwise 219*90eb1077SAndy Ritger */ 220*90eb1077SAndy Ritger NvBool 221*90eb1077SAndy Ritger kfspIsQueueEmpty_IMPL 222*90eb1077SAndy Ritger ( 223*90eb1077SAndy Ritger OBJGPU *pGpu, 224*90eb1077SAndy Ritger KernelFsp *pKernelFsp 225*90eb1077SAndy Ritger ) 226*90eb1077SAndy Ritger { 227*90eb1077SAndy Ritger NvU32 cmdqHead, cmdqTail; 228*90eb1077SAndy Ritger 229*90eb1077SAndy Ritger kfspGetQueueHeadTail_HAL(pGpu, pKernelFsp, &cmdqHead, &cmdqTail); 230*90eb1077SAndy Ritger 231*90eb1077SAndy Ritger // FSP will set QUEUE_HEAD = TAIL after each packet is received 232*90eb1077SAndy Ritger return (cmdqHead == cmdqTail); 233*90eb1077SAndy Ritger } 234*90eb1077SAndy Ritger 235*90eb1077SAndy Ritger /*! 236*90eb1077SAndy Ritger * @brief Wait for FSP RM command queue to be empty 237*90eb1077SAndy Ritger * 238*90eb1077SAndy Ritger * @param[in] pGpu OBJGPU pointer 239*90eb1077SAndy Ritger * @param[in] pKernelFsp KernelFsp pointer 240*90eb1077SAndy Ritger * 241*90eb1077SAndy Ritger * @return NV_OK, or NV_ERR_TIMEOUT 242*90eb1077SAndy Ritger */ 243*90eb1077SAndy Ritger NV_STATUS 244*90eb1077SAndy Ritger kfspPollForQueueEmpty_IMPL 245*90eb1077SAndy Ritger ( 246*90eb1077SAndy Ritger OBJGPU *pGpu, 247*90eb1077SAndy Ritger KernelFsp *pKernelFsp 248*90eb1077SAndy Ritger ) 249*90eb1077SAndy Ritger { 250*90eb1077SAndy Ritger RMTIMEOUT timeout; 251*90eb1077SAndy Ritger 252*90eb1077SAndy Ritger gpuSetTimeout(pGpu, GPU_TIMEOUT_DEFAULT, &timeout, 0); 253*90eb1077SAndy Ritger 254*90eb1077SAndy Ritger while (!kfspIsQueueEmpty(pGpu, pKernelFsp)) 255*90eb1077SAndy Ritger { 256*90eb1077SAndy Ritger // 257*90eb1077SAndy Ritger // For now we assume that any response from FSP before RM message send is complete 258*90eb1077SAndy Ritger // indicates an error and we should abort. 259*90eb1077SAndy Ritger // 260*90eb1077SAndy Ritger if (!kfspIsMsgQueueEmpty(pGpu, pKernelFsp)) 261*90eb1077SAndy Ritger { 262*90eb1077SAndy Ritger kfspReadMessage(pGpu, pKernelFsp, NULL, 0); 263*90eb1077SAndy Ritger NV_PRINTF(LEVEL_ERROR, "Received error message from FSP while waiting for CMDQ to be empty.\n"); 264*90eb1077SAndy Ritger return NV_ERR_GENERIC; 265*90eb1077SAndy Ritger } 266*90eb1077SAndy Ritger 267*90eb1077SAndy Ritger if (gpuCheckTimeout(pGpu, &timeout) == NV_ERR_TIMEOUT) 268*90eb1077SAndy Ritger { 269*90eb1077SAndy Ritger NV_PRINTF(LEVEL_ERROR, "Timed out waiting for FSP command queue to be empty.\n"); 270*90eb1077SAndy Ritger return NV_ERR_TIMEOUT; 271*90eb1077SAndy Ritger } 272*90eb1077SAndy Ritger osSpinLoop(); 273*90eb1077SAndy Ritger } 274*90eb1077SAndy Ritger 275*90eb1077SAndy Ritger return NV_OK; 276*90eb1077SAndy Ritger } 277*90eb1077SAndy Ritger 278*90eb1077SAndy Ritger /*! 279*90eb1077SAndy Ritger * @brief Check if FSP RM message queue is empty 280*90eb1077SAndy Ritger * 281*90eb1077SAndy Ritger * @param[in] pGpu OBJGPU pointer 282*90eb1077SAndy Ritger * @param[in] pKernelFsp KernelFsp pointer 283*90eb1077SAndy Ritger * 284*90eb1077SAndy Ritger * @return NV_TRUE if queue is empty, NV_FALSE otherwise 285*90eb1077SAndy Ritger */ 286*90eb1077SAndy Ritger NvBool 287*90eb1077SAndy Ritger kfspIsMsgQueueEmpty_IMPL 288*90eb1077SAndy Ritger ( 289*90eb1077SAndy Ritger OBJGPU *pGpu, 290*90eb1077SAndy Ritger KernelFsp *pKernelFsp 291*90eb1077SAndy Ritger ) 292*90eb1077SAndy Ritger { 293*90eb1077SAndy Ritger NvU32 msgqHead, msgqTail; 294*90eb1077SAndy Ritger 295*90eb1077SAndy Ritger kfspGetMsgQueueHeadTail_HAL(pGpu, pKernelFsp, &msgqHead, &msgqTail); 296*90eb1077SAndy Ritger return (msgqHead == msgqTail); 297*90eb1077SAndy Ritger } 298*90eb1077SAndy Ritger 299*90eb1077SAndy Ritger /*! 300*90eb1077SAndy Ritger * @brief Poll for response from FSP via RM message queue 301*90eb1077SAndy Ritger * 302*90eb1077SAndy Ritger * @param[in] pGpu OBJGPU pointer 303*90eb1077SAndy Ritger * @param[in] pKernelFsp KernelFsp pointer 304*90eb1077SAndy Ritger * 305*90eb1077SAndy Ritger * @return NV_OK, or NV_ERR_TIMEOUT 306*90eb1077SAndy Ritger */ 307*90eb1077SAndy Ritger NV_STATUS 308*90eb1077SAndy Ritger kfspPollForResponse_IMPL 309*90eb1077SAndy Ritger ( 310*90eb1077SAndy Ritger OBJGPU *pGpu, 311*90eb1077SAndy Ritger KernelFsp *pKernelFsp 312*90eb1077SAndy Ritger ) 313*90eb1077SAndy Ritger { 314*90eb1077SAndy Ritger RMTIMEOUT timeout; 315*90eb1077SAndy Ritger NV_STATUS status = NV_OK; 316*90eb1077SAndy Ritger 317*90eb1077SAndy Ritger // Poll for message queue to wait for FSP's reply 318*90eb1077SAndy Ritger gpuSetTimeout(pGpu, GPU_TIMEOUT_DEFAULT, &timeout, 0); 319*90eb1077SAndy Ritger while (kfspIsMsgQueueEmpty(pGpu, pKernelFsp)) 320*90eb1077SAndy Ritger { 321*90eb1077SAndy Ritger if (gpuCheckTimeout(pGpu, &timeout) == NV_ERR_TIMEOUT) 322*90eb1077SAndy Ritger { 323*90eb1077SAndy Ritger NV_PRINTF(LEVEL_ERROR, "FSP command timed out\n"); 324*90eb1077SAndy Ritger return NV_ERR_TIMEOUT; 325*90eb1077SAndy Ritger } 326*90eb1077SAndy Ritger 327*90eb1077SAndy Ritger osSpinLoop(); 328*90eb1077SAndy Ritger } 329*90eb1077SAndy Ritger 330*90eb1077SAndy Ritger return status; 331*90eb1077SAndy Ritger } 332*90eb1077SAndy Ritger 333*90eb1077SAndy Ritger /*! 334*90eb1077SAndy Ritger * @brief Read and process message from FSP via RM message queue. 335*90eb1077SAndy Ritger * 336*90eb1077SAndy Ritger * Supports both single and multi-packet message. For multi-packet messages, this 337*90eb1077SAndy Ritger * loops until all packets are received, polling at each iteration for the next 338*90eb1077SAndy Ritger * packet to come in. If a buffer is provided, the message payload will be 339*90eb1077SAndy Ritger * returned there. 340*90eb1077SAndy Ritger * 341*90eb1077SAndy Ritger * @note: For multi-packet messages, a buffer in which the message payload will 342*90eb1077SAndy Ritger * be reconstructed must be provided. 343*90eb1077SAndy Ritger * 344*90eb1077SAndy Ritger * @param[in] pGpu OBJGPU pointer 345*90eb1077SAndy Ritger * @param[in] pKernelFsp KernelFsp pointer 346*90eb1077SAndy Ritger * @param[in/out] pPayloadBuffer Buffer in which to return message payload 347*90eb1077SAndy Ritger * @param[in] payloadBufferSize Payload buffer size 348*90eb1077SAndy Ritger * 349*90eb1077SAndy Ritger * @return NV_OK, NV_ERR_INVALID_DATA, NV_ERR_INSUFFICIENT_RESOURCES, or errors 350*90eb1077SAndy Ritger * from functions called within 351*90eb1077SAndy Ritger */ 352*90eb1077SAndy Ritger static NV_STATUS 353*90eb1077SAndy Ritger kfspReadMessage 354*90eb1077SAndy Ritger ( 355*90eb1077SAndy Ritger OBJGPU *pGpu, 356*90eb1077SAndy Ritger KernelFsp *pKernelFsp, 357*90eb1077SAndy Ritger NvU8 *pPayloadBuffer, 358*90eb1077SAndy Ritger NvU32 payloadBufferSize 359*90eb1077SAndy Ritger ) 360*90eb1077SAndy Ritger { 361*90eb1077SAndy Ritger NvU8 *pPacketBuffer; 362*90eb1077SAndy Ritger NV_STATUS status; 363*90eb1077SAndy Ritger NvU32 totalPayloadSize = 0; 364*90eb1077SAndy Ritger MCTP_PACKET_STATE packetState = MCTP_PACKET_STATE_START; 365*90eb1077SAndy Ritger 366*90eb1077SAndy Ritger if (kfspIsMsgQueueEmpty(pGpu, pKernelFsp)) 367*90eb1077SAndy Ritger { 368*90eb1077SAndy Ritger NV_PRINTF(LEVEL_WARNING, "Tried to read FSP response but MSG queue is empty\n"); 369*90eb1077SAndy Ritger return NV_OK; 370*90eb1077SAndy Ritger } 371*90eb1077SAndy Ritger 372*90eb1077SAndy Ritger pPacketBuffer = portMemAllocNonPaged(kfspGetRmChannelSize_HAL(pGpu, pKernelFsp)); 373*90eb1077SAndy Ritger 374*90eb1077SAndy Ritger while ((packetState != MCTP_PACKET_STATE_END) && (packetState != MCTP_PACKET_STATE_SINGLE_PACKET)) 375*90eb1077SAndy Ritger { 376*90eb1077SAndy Ritger NvU32 msgqHead, msgqTail; 377*90eb1077SAndy Ritger NvU32 packetSize; 378*90eb1077SAndy Ritger NvU32 curPayloadSize; 379*90eb1077SAndy Ritger NvU8 curHeaderSize; 380*90eb1077SAndy Ritger NvU8 tag; 381*90eb1077SAndy Ritger 382*90eb1077SAndy Ritger // Wait for next packet 383*90eb1077SAndy Ritger status = kfspPollForResponse(pGpu, pKernelFsp); 384*90eb1077SAndy Ritger if (status != NV_OK) 385*90eb1077SAndy Ritger { 386*90eb1077SAndy Ritger goto done; 387*90eb1077SAndy Ritger } 388*90eb1077SAndy Ritger 389*90eb1077SAndy Ritger kfspGetMsgQueueHeadTail_HAL(pGpu, pKernelFsp, &msgqHead, &msgqTail); 390*90eb1077SAndy Ritger 391*90eb1077SAndy Ritger // Tail points to last DWORD in packet, not DWORD immediately following it 392*90eb1077SAndy Ritger packetSize = (msgqTail - msgqHead) + sizeof(NvU32); 393*90eb1077SAndy Ritger 394*90eb1077SAndy Ritger if ((packetSize < sizeof(NvU32)) || 395*90eb1077SAndy Ritger (packetSize > kfspGetRmChannelSize_HAL(pGpu, pKernelFsp))) 396*90eb1077SAndy Ritger { 397*90eb1077SAndy Ritger NV_PRINTF(LEVEL_ERROR, "FSP response packet is invalid size: size=0x%x bytes\n", packetSize); 398*90eb1077SAndy Ritger status = NV_ERR_INVALID_DATA; 399*90eb1077SAndy Ritger goto done; 400*90eb1077SAndy Ritger } 401*90eb1077SAndy Ritger 402*90eb1077SAndy Ritger kfspReadFromEmem_HAL(pGpu, pKernelFsp, pPacketBuffer, packetSize); 403*90eb1077SAndy Ritger 404*90eb1077SAndy Ritger status = kfspGetPacketInfo_HAL(pGpu, pKernelFsp, pPacketBuffer, packetSize, &packetState, &tag); 405*90eb1077SAndy Ritger if (status != NV_OK) 406*90eb1077SAndy Ritger { 407*90eb1077SAndy Ritger goto done; 408*90eb1077SAndy Ritger } 409*90eb1077SAndy Ritger 410*90eb1077SAndy Ritger if ((packetState == MCTP_PACKET_STATE_START) || (packetState == MCTP_PACKET_STATE_SINGLE_PACKET)) 411*90eb1077SAndy Ritger { 412*90eb1077SAndy Ritger // Packet contains payload header 413*90eb1077SAndy Ritger curHeaderSize = sizeof(MCTP_HEADER); 414*90eb1077SAndy Ritger } 415*90eb1077SAndy Ritger else 416*90eb1077SAndy Ritger { 417*90eb1077SAndy Ritger curHeaderSize = sizeof(NvU32); 418*90eb1077SAndy Ritger } 419*90eb1077SAndy Ritger 420*90eb1077SAndy Ritger curPayloadSize = packetSize - curHeaderSize; 421*90eb1077SAndy Ritger 422*90eb1077SAndy Ritger if ((pPayloadBuffer == NULL) && (packetState != MCTP_PACKET_STATE_SINGLE_PACKET)) 423*90eb1077SAndy Ritger { 424*90eb1077SAndy Ritger NV_PRINTF(LEVEL_ERROR, "No buffer provided when receiving multi-packet message. Buffer needed to reconstruct message\n"); 425*90eb1077SAndy Ritger status = NV_ERR_INSUFFICIENT_RESOURCES; 426*90eb1077SAndy Ritger goto done; 427*90eb1077SAndy Ritger } 428*90eb1077SAndy Ritger 429*90eb1077SAndy Ritger if (pPayloadBuffer != NULL) 430*90eb1077SAndy Ritger { 431*90eb1077SAndy Ritger if (payloadBufferSize < (totalPayloadSize + curPayloadSize)) 432*90eb1077SAndy Ritger { 433*90eb1077SAndy Ritger NV_PRINTF(LEVEL_ERROR, "Buffer provided for message payload too small. Payload size: 0x%x Buffer size: 0x%x\n", 434*90eb1077SAndy Ritger totalPayloadSize + curPayloadSize, payloadBufferSize); 435*90eb1077SAndy Ritger status = NV_ERR_INSUFFICIENT_RESOURCES; 436*90eb1077SAndy Ritger goto done; 437*90eb1077SAndy Ritger } 438*90eb1077SAndy Ritger portMemCopy(pPayloadBuffer + totalPayloadSize, payloadBufferSize - totalPayloadSize , 439*90eb1077SAndy Ritger pPacketBuffer + curHeaderSize, curPayloadSize); 440*90eb1077SAndy Ritger } 441*90eb1077SAndy Ritger totalPayloadSize += curPayloadSize; 442*90eb1077SAndy Ritger 443*90eb1077SAndy Ritger // Set TAIL = HEAD to indicate CPU received message 444*90eb1077SAndy Ritger kfspUpdateMsgQueueHeadTail_HAL(pGpu, pKernelFsp, msgqHead, msgqHead); 445*90eb1077SAndy Ritger } 446*90eb1077SAndy Ritger 447*90eb1077SAndy Ritger NvU8 *pMessagePayload = (pPayloadBuffer == NULL) ? (pPacketBuffer + sizeof(MCTP_HEADER)) : pPayloadBuffer; 448*90eb1077SAndy Ritger 449*90eb1077SAndy Ritger status = kfspProcessNvdmMessage_HAL(pGpu, pKernelFsp, pMessagePayload, totalPayloadSize); 450*90eb1077SAndy Ritger 451*90eb1077SAndy Ritger done: 452*90eb1077SAndy Ritger portMemFree(pPacketBuffer); 453*90eb1077SAndy Ritger return status; 454*90eb1077SAndy Ritger } 455*90eb1077SAndy Ritger 456*90eb1077SAndy Ritger /*! 457*90eb1077SAndy Ritger * @brief Send one MCTP packet to FSP via EMEM 458*90eb1077SAndy Ritger * 459*90eb1077SAndy Ritger * @param[in] pGpu OBJGPU pointer 460*90eb1077SAndy Ritger * @param[in] pKernelFsp KernelFsp pointer 461*90eb1077SAndy Ritger * @param[in] pPacket MCTP packet 462*90eb1077SAndy Ritger * @param[in] packetSize MCTP packet size in bytes 463*90eb1077SAndy Ritger * 464*90eb1077SAndy Ritger * @return NV_OK, or NV_ERR_INSUFFICIENT_RESOURCES 465*90eb1077SAndy Ritger */ 466*90eb1077SAndy Ritger NV_STATUS 467*90eb1077SAndy Ritger kfspSendPacket_IMPL 468*90eb1077SAndy Ritger ( 469*90eb1077SAndy Ritger OBJGPU *pGpu, 470*90eb1077SAndy Ritger KernelFsp *pKernelFsp, 471*90eb1077SAndy Ritger NvU8 *pPacket, 472*90eb1077SAndy Ritger NvU32 packetSize 473*90eb1077SAndy Ritger ) 474*90eb1077SAndy Ritger { 475*90eb1077SAndy Ritger NvU32 paddedSize; 476*90eb1077SAndy Ritger NvU8 *pBuffer = NULL; 477*90eb1077SAndy Ritger NV_STATUS status = NV_OK; 478*90eb1077SAndy Ritger 479*90eb1077SAndy Ritger // Check that queue is ready to receive data 480*90eb1077SAndy Ritger status = kfspPollForQueueEmpty(pGpu, pKernelFsp); 481*90eb1077SAndy Ritger if (status != NV_OK) 482*90eb1077SAndy Ritger { 483*90eb1077SAndy Ritger return NV_ERR_INSUFFICIENT_RESOURCES; 484*90eb1077SAndy Ritger } 485*90eb1077SAndy Ritger 486*90eb1077SAndy Ritger // Pad to align size to 4-bytes boundary since EMEMC increments by DWORDS 487*90eb1077SAndy Ritger paddedSize = NV_ALIGN_UP(packetSize, sizeof(NvU32)); 488*90eb1077SAndy Ritger pBuffer = portMemAllocNonPaged(paddedSize); 489*90eb1077SAndy Ritger portMemSet(pBuffer, 0, paddedSize); 490*90eb1077SAndy Ritger portMemCopy(pBuffer, paddedSize, pPacket, paddedSize); 491*90eb1077SAndy Ritger 492*90eb1077SAndy Ritger kfspWriteToEmem_HAL(pGpu, pKernelFsp, pBuffer, paddedSize); 493*90eb1077SAndy Ritger 494*90eb1077SAndy Ritger // Update HEAD and TAIL with new EMEM offset; RM always starts at offset 0. 495*90eb1077SAndy Ritger kfspUpdateQueueHeadTail_HAL(pGpu, pKernelFsp, 0, paddedSize - sizeof(NvU32)); 496*90eb1077SAndy Ritger 497*90eb1077SAndy Ritger portMemFree(pBuffer); 498*90eb1077SAndy Ritger return status; 499*90eb1077SAndy Ritger } 500*90eb1077SAndy Ritger 501*90eb1077SAndy Ritger /*! 502*90eb1077SAndy Ritger * @brief Send a MCTP message to FSP via EMEM, and read response 503*90eb1077SAndy Ritger * 504*90eb1077SAndy Ritger * 505*90eb1077SAndy Ritger * Response payload buffer is optional if response fits in a single packet. 506*90eb1077SAndy Ritger * 507*90eb1077SAndy Ritger * @param[in] pGpu OBJGPU pointer 508*90eb1077SAndy Ritger * @param[in] pKernelFsp KernelFsp pointer 509*90eb1077SAndy Ritger * @param[in] pPayload Pointer to message payload 510*90eb1077SAndy Ritger * @param[in] size Message payload size 511*90eb1077SAndy Ritger * @param[in] nvdmType NVDM type of message being sent 512*90eb1077SAndy Ritger * @param[in] pResponsePayload Buffer in which to return response payload 513*90eb1077SAndy Ritger * @param[in] responseBufferSize Response payload buffer size 514*90eb1077SAndy Ritger * 515*90eb1077SAndy Ritger * @return NV_OK, or NV_ERR_* 516*90eb1077SAndy Ritger */ 517*90eb1077SAndy Ritger NV_STATUS 518*90eb1077SAndy Ritger kfspSendAndReadMessage_IMPL 519*90eb1077SAndy Ritger ( 520*90eb1077SAndy Ritger OBJGPU *pGpu, 521*90eb1077SAndy Ritger KernelFsp *pKernelFsp, 522*90eb1077SAndy Ritger NvU8 *pPayload, 523*90eb1077SAndy Ritger NvU32 size, 524*90eb1077SAndy Ritger NvU32 nvdmType, 525*90eb1077SAndy Ritger NvU8 *pResponsePayload, 526*90eb1077SAndy Ritger NvU32 responseBufferSize 527*90eb1077SAndy Ritger ) 528*90eb1077SAndy Ritger { 529*90eb1077SAndy Ritger NvU32 dataSent, dataRemaining; 530*90eb1077SAndy Ritger NvU32 packetPayloadCapacity; 531*90eb1077SAndy Ritger NvU32 curPayloadSize; 532*90eb1077SAndy Ritger NvU32 headerSize; 533*90eb1077SAndy Ritger NvU32 fspEmemRmChannelSize; 534*90eb1077SAndy Ritger NvBool bSinglePacket; 535*90eb1077SAndy Ritger NV_STATUS status; 536*90eb1077SAndy Ritger NvU8 *pBuffer = NULL; 537*90eb1077SAndy Ritger NvU8 seq = 0; 538*90eb1077SAndy Ritger NvU8 seid = 0; 539*90eb1077SAndy Ritger 540*90eb1077SAndy Ritger // Allocate buffer of same size as channel 541*90eb1077SAndy Ritger fspEmemRmChannelSize = kfspGetRmChannelSize_HAL(pGpu, pKernelFsp); 542*90eb1077SAndy Ritger pBuffer = portMemAllocNonPaged(fspEmemRmChannelSize); 543*90eb1077SAndy Ritger portMemSet(pBuffer, 0, fspEmemRmChannelSize); 544*90eb1077SAndy Ritger 545*90eb1077SAndy Ritger // 546*90eb1077SAndy Ritger // Check if message will fit in single packet 547*90eb1077SAndy Ritger // We lose 2 DWORDS to MCTP and NVDM headers 548*90eb1077SAndy Ritger // 549*90eb1077SAndy Ritger headerSize = 2 * sizeof(NvU32); 550*90eb1077SAndy Ritger packetPayloadCapacity = fspEmemRmChannelSize - headerSize; 551*90eb1077SAndy Ritger bSinglePacket = (size <= packetPayloadCapacity); 552*90eb1077SAndy Ritger 553*90eb1077SAndy Ritger // First packet 554*90eb1077SAndy Ritger seid = kfspNvdmToSeid_HAL(pGpu, pKernelFsp, nvdmType); 555*90eb1077SAndy Ritger ((NvU32 *)pBuffer)[0] = kfspCreateMctpHeader_HAL(pGpu, pKernelFsp, 1, (NvU8)bSinglePacket, seid, seq); // SOM=1,EOM=?,SEID,SEQ=0 556*90eb1077SAndy Ritger ((NvU32 *)pBuffer)[1] = kfspCreateNvdmHeader_HAL(pGpu, pKernelFsp, nvdmType); 557*90eb1077SAndy Ritger 558*90eb1077SAndy Ritger curPayloadSize = NV_MIN(size, packetPayloadCapacity); 559*90eb1077SAndy Ritger portMemCopy(pBuffer + headerSize, packetPayloadCapacity, pPayload, curPayloadSize); 560*90eb1077SAndy Ritger 561*90eb1077SAndy Ritger status = kfspSendPacket(pGpu, pKernelFsp, pBuffer, curPayloadSize + headerSize); 562*90eb1077SAndy Ritger if (status != NV_OK) 563*90eb1077SAndy Ritger { 564*90eb1077SAndy Ritger goto failed; 565*90eb1077SAndy Ritger } 566*90eb1077SAndy Ritger 567*90eb1077SAndy Ritger if (!bSinglePacket) 568*90eb1077SAndy Ritger { 569*90eb1077SAndy Ritger // Multi packet case 570*90eb1077SAndy Ritger dataSent = curPayloadSize; 571*90eb1077SAndy Ritger dataRemaining = size - dataSent; 572*90eb1077SAndy Ritger headerSize = sizeof(NvU32); // No longer need NVDM header 573*90eb1077SAndy Ritger packetPayloadCapacity = fspEmemRmChannelSize - headerSize; 574*90eb1077SAndy Ritger 575*90eb1077SAndy Ritger while (dataRemaining > 0) 576*90eb1077SAndy Ritger { 577*90eb1077SAndy Ritger NvBool bLastPacket = (dataRemaining <= packetPayloadCapacity); 578*90eb1077SAndy Ritger curPayloadSize = (bLastPacket) ? dataRemaining : packetPayloadCapacity; 579*90eb1077SAndy Ritger 580*90eb1077SAndy Ritger portMemSet(pBuffer, 0, fspEmemRmChannelSize); 581*90eb1077SAndy Ritger ((NvU32 *)pBuffer)[0] = kfspCreateMctpHeader_HAL(pGpu, pKernelFsp, 0, (NvU8)bLastPacket, seid, (++seq) % 4); 582*90eb1077SAndy Ritger 583*90eb1077SAndy Ritger portMemCopy(pBuffer + headerSize, packetPayloadCapacity, 584*90eb1077SAndy Ritger pPayload + dataSent, curPayloadSize); 585*90eb1077SAndy Ritger 586*90eb1077SAndy Ritger status = kfspSendPacket(pGpu, pKernelFsp, pBuffer, curPayloadSize + headerSize); 587*90eb1077SAndy Ritger if (status != NV_OK) 588*90eb1077SAndy Ritger { 589*90eb1077SAndy Ritger goto failed; 590*90eb1077SAndy Ritger } 591*90eb1077SAndy Ritger 592*90eb1077SAndy Ritger dataSent += curPayloadSize; 593*90eb1077SAndy Ritger dataRemaining -= curPayloadSize; 594*90eb1077SAndy Ritger } 595*90eb1077SAndy Ritger 596*90eb1077SAndy Ritger } 597*90eb1077SAndy Ritger 598*90eb1077SAndy Ritger status = kfspPollForResponse(pGpu, pKernelFsp); 599*90eb1077SAndy Ritger if (status != NV_OK) 600*90eb1077SAndy Ritger { 601*90eb1077SAndy Ritger goto failed; 602*90eb1077SAndy Ritger } 603*90eb1077SAndy Ritger status = kfspReadMessage(pGpu, pKernelFsp, pResponsePayload, responseBufferSize); 604*90eb1077SAndy Ritger 605*90eb1077SAndy Ritger failed: 606*90eb1077SAndy Ritger portMemFree(pBuffer); 607*90eb1077SAndy Ritger 608*90eb1077SAndy Ritger return status; 609*90eb1077SAndy Ritger } 610