515.43.04

This commit is contained in:
Andy Ritger
2022-05-09 13:18:59 -07:00
commit 1739a20efc
2519 changed files with 1060036 additions and 0 deletions

View File

@@ -0,0 +1,734 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2020-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* 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 "nvfixedtypes.h"
#include "common_nvswitch.h"
#include "error_nvswitch.h"
#include "rmsoecmdif.h"
#include "smbpbi_nvswitch.h"
#include "nvswitch/lr10/dev_ext_devices.h"
#include "flcn/flcn_nvswitch.h"
#include "rmflcncmdif_nvswitch.h"
#define GET_PFIFO_FROM_DEVICE(dev) (&(dev)->pSmbpbi->sharedSurface->inforomObjects.DEM.object.v1)
#define DEM_FIFO_SIZE INFOROM_DEM_OBJECT_V1_00_FIFO_SIZE
#define DEM_FIFO_PTR(x) ((x) % DEM_FIFO_SIZE)
#define DEM_PTR_DIFF(cur, next) (((next) > (cur)) ? ((next) - (cur)) : \
(DEM_FIFO_SIZE - ((cur) - (next))))
#define DEM_BYTES_OCCUPIED(pf) DEM_PTR_DIFF((pf)->readOffset, (pf)->writeOffset)
//
// See how much space is available in the FIFO.
// Must leave 1 word free so the write pointer does not
// catch up with the read pointer. That would be indistinguishable
// from an empty FIFO.
//
#define DEM_BYTES_AVAILABLE(pf) (DEM_PTR_DIFF((pf)->writeOffset, (pf)->readOffset) - \
sizeof(NvU32))
#define DEM_RECORD_SIZE_MAX (sizeof(NV_MSGBOX_DEM_RECORD) \
+ NV_MSGBOX_MAX_DRIVER_EVENT_MSG_TXT_SIZE)
#define DEM_RECORD_SIZE_MIN (sizeof(NV_MSGBOX_DEM_RECORD) + 1)
#define FIFO_REC_LOOP_ITERATOR _curPtr
#define FIFO_REC_LOOP_REC_PTR _recPtr
#define FIFO_REC_LOOP_REC_SIZE _recSize
#define FIFO_REC_LOOP_START(pf, cond) \
{ \
NvU16 _nextPtr; \
for (FIFO_REC_LOOP_ITERATOR = (pf)->readOffset; cond; FIFO_REC_LOOP_ITERATOR = _nextPtr) \
{ \
NV_MSGBOX_DEM_RECORD *FIFO_REC_LOOP_REC_PTR = (NV_MSGBOX_DEM_RECORD *) \
((pf)->fifoBuffer + FIFO_REC_LOOP_ITERATOR); \
NvU16 FIFO_REC_LOOP_REC_SIZE = \
FIFO_REC_LOOP_REC_PTR->recordSize * sizeof(NvU32);
#define FIFO_REC_LOOP_END \
_nextPtr = DEM_FIFO_PTR(FIFO_REC_LOOP_ITERATOR + FIFO_REC_LOOP_REC_SIZE); \
} \
}
static void _smbpbiDemInit(nvswitch_device *device, struct smbpbi *pSmbpbi, struct INFOROM_DEM_OBJECT_V1_00 *pFifo);
static void _nvswitch_smbpbi_dem_flush(nvswitch_device *device);
NvlStatus
nvswitch_smbpbi_init
(
nvswitch_device *device
)
{
NV_STATUS status;
NvU64 dmaHandle;
void *cpuAddr;
if (!device->pSoe)
{
return -NVL_ERR_INVALID_STATE;
}
// Create DMA mapping for SMBPBI transactions
status = nvswitch_os_alloc_contig_memory(device->os_handle, &cpuAddr,
sizeof(SOE_SMBPBI_SHARED_SURFACE),
(device->dma_addr_width == 32));
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR, "Failed to allocate contig memory, rc:%d\n",
status);
return status;
}
nvswitch_os_memset(cpuAddr, 0, sizeof(SOE_SMBPBI_SHARED_SURFACE));
status = nvswitch_os_map_dma_region(device->os_handle, cpuAddr, &dmaHandle,
sizeof(SOE_SMBPBI_SHARED_SURFACE),
NVSWITCH_DMA_DIR_BIDIRECTIONAL);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"Failed to map dma region for SMBPBI shared surface, rc:%d\n",
status);
goto os_map_dma_region_fail;
}
device->pSmbpbi = nvswitch_os_malloc(sizeof(struct smbpbi));
if (!device->pSmbpbi)
{
status = -NVL_NO_MEM;
goto smbpbi_init_fail;
}
device->pSmbpbi->sharedSurface = cpuAddr;
device->pSmbpbi->dmaHandle = dmaHandle;
return NVL_SUCCESS;
smbpbi_init_fail:
nvswitch_os_unmap_dma_region(device->os_handle, cpuAddr, dmaHandle,
sizeof(SOE_SMBPBI_SHARED_SURFACE), NVSWITCH_DMA_DIR_BIDIRECTIONAL);
os_map_dma_region_fail:
nvswitch_os_free_contig_memory(device->os_handle, cpuAddr, sizeof(SOE_SMBPBI_SHARED_SURFACE));
return status;
}
NvlStatus
nvswitch_smbpbi_post_init
(
nvswitch_device * device
)
{
struct smbpbi *pSmbpbi = device->pSmbpbi;
FLCN *pFlcn;
NvU64 dmaHandle;
RM_FLCN_CMD_SOE cmd;
NVSWITCH_TIMEOUT timeout;
NvU32 cmdSeqDesc;
RM_SOE_SMBPBI_CMD_INIT *pInitCmd = &cmd.cmd.smbpbiCmd.init;
NvlStatus status;
if (!device->pSmbpbi || !device->pInforom)
{
return -NVL_ERR_NOT_SUPPORTED;
}
// Populate shared surface with static InfoROM data
nvswitch_inforom_read_static_data(device, device->pInforom,
&device->pSmbpbi->sharedSurface->inforomObjects);
pFlcn = device->pSoe->pFlcn;
dmaHandle = pSmbpbi->dmaHandle;
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
cmd.hdr.unitId = RM_SOE_UNIT_SMBPBI;
cmd.hdr.size = RM_SOE_CMD_SIZE(SMBPBI, INIT);
cmd.cmd.smbpbiCmd.cmdType = RM_SOE_SMBPBI_CMD_ID_INIT;
RM_FLCN_U64_PACK(&pInitCmd->dmaHandle, &dmaHandle);
//
// Make the interval twice the heartbeat period to avoid
// skew between driver and soe threads
//
pInitCmd->driverPollingPeriodUs = (NVSWITCH_HEARTBEAT_INTERVAL_NS / 1000) * 2;
nvswitch_timeout_create(NVSWITCH_INTERVAL_1SEC_IN_NS, &timeout);
status = flcnQueueCmdPostBlocking(device, pFlcn,
(PRM_FLCN_CMD)&cmd,
NULL, // pMsg - not used for now
NULL, // pPayload - not used for now
SOE_RM_CMDQ_LOG_ID,
&cmdSeqDesc,
&timeout);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR, "%s: SMBPBI Init command failed. rc:%d\n",
__FUNCTION__, status);
return status;
}
nvswitch_lib_smbpbi_log_sxid(device, NVSWITCH_ERR_NO_ERROR,
"NVSWITCH SMBPBI server is online.");
NVSWITCH_PRINT(device, INFO, "%s: SMBPBI POST INIT completed\n", __FUNCTION__);
return NVL_SUCCESS;
}
static void
_nvswitch_smbpbi_send_unload
(
nvswitch_device *device
)
{
FLCN *pFlcn;
RM_FLCN_CMD_SOE cmd;
NVSWITCH_TIMEOUT timeout;
NvU32 cmdSeqDesc;
NvlStatus status;
pFlcn = device->pSoe->pFlcn;
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
cmd.hdr.unitId = RM_SOE_UNIT_SMBPBI;
cmd.hdr.size = RM_SOE_CMD_SIZE(SMBPBI, UNLOAD);
cmd.cmd.smbpbiCmd.cmdType = RM_SOE_SMBPBI_CMD_ID_UNLOAD;
nvswitch_timeout_create(NVSWITCH_INTERVAL_1SEC_IN_NS, &timeout);
status = flcnQueueCmdPostBlocking(device, pFlcn,
(PRM_FLCN_CMD)&cmd,
NULL, // pMsg - not used for now
NULL, // pPayload - not used for now
SOE_RM_CMDQ_LOG_ID,
&cmdSeqDesc,
&timeout);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR, "%s: SMBPBI unload command failed. rc:%d\n",
__FUNCTION__, status);
}
}
void
nvswitch_smbpbi_unload
(
nvswitch_device *device
)
{
if (device->pSmbpbi)
{
_nvswitch_smbpbi_send_unload(device);
_nvswitch_smbpbi_dem_flush(device);
}
}
void
nvswitch_smbpbi_destroy
(
nvswitch_device *device
)
{
if (device->pSmbpbi)
{
nvswitch_os_unmap_dma_region(device->os_handle,
device->pSmbpbi->sharedSurface,
device->pSmbpbi->dmaHandle,
sizeof(SOE_SMBPBI_SHARED_SURFACE),
NVSWITCH_DMA_DIR_BIDIRECTIONAL);
nvswitch_os_free_contig_memory(device->os_handle, device->pSmbpbi->sharedSurface,
sizeof(SOE_SMBPBI_SHARED_SURFACE));
nvswitch_os_free(device->pSmbpbi);
device->pSmbpbi = NULL;
}
}
NvlStatus
nvswitch_smbpbi_refresh_ecc_counts
(
nvswitch_device *device
)
{
PRM_SOE_SMBPBI_INFOROM_DATA pObjs;
struct inforom *pInforom = device->pInforom;
NvU64 corCnt;
NvU64 uncCnt;
if ((device->pSmbpbi == NULL) || (device->pSmbpbi->sharedSurface == NULL))
{
return -NVL_ERR_NOT_SUPPORTED;
}
if (pInforom == NULL || pInforom->pEccState == NULL)
{
return -NVL_ERR_NOT_SUPPORTED;
}
device->hal.nvswitch_inforom_ecc_get_total_errors(device, pInforom->pEccState->pEcc,
&corCnt, &uncCnt);
pObjs = &device->pSmbpbi->sharedSurface->inforomObjects;
NvU64_ALIGN32_PACK(&(pObjs->ECC.correctedTotal), &corCnt);
NvU64_ALIGN32_PACK(&(pObjs->ECC.uncorrectedTotal), &uncCnt);
return NVL_SUCCESS;
}
NvlStatus
nvswitch_inforom_dem_load
(
nvswitch_device *device
)
{
NvlStatus status;
NvU8 version = 0;
NvU8 subversion = 0;
struct inforom *pInforom = device->pInforom;
NvU8 *pPackedObject = NULL;
struct INFOROM_DEM_OBJECT_V1_00 *pFifo;
if ((pInforom == NULL) || (device->pSmbpbi == NULL) ||
(device->pSmbpbi->sharedSurface == NULL))
{
return -NVL_ERR_NOT_SUPPORTED;
}
pFifo = GET_PFIFO_FROM_DEVICE(device);
status = nvswitch_inforom_get_object_version_info(device, "DEM", &version,
&subversion);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, INFO, "no DEM object found, rc:%d\n", status);
goto nvswitch_inforom_dem_load_fail;
}
if (!INFOROM_OBJECT_SUBVERSION_SUPPORTS_NVSWITCH(subversion))
{
NVSWITCH_PRINT(device, WARN, "DEM v%u.%u not supported\n",
version, subversion);
status = -NVL_ERR_NOT_SUPPORTED;
goto nvswitch_inforom_dem_load_fail;
}
NVSWITCH_PRINT(device, INFO, "DEM v%u.%u found\n", version, subversion);
if (version != 1)
{
NVSWITCH_PRINT(device, WARN, "DEM v%u.%u not supported\n",
version, subversion);
status = -NVL_ERR_NOT_SUPPORTED;
goto nvswitch_inforom_dem_load_fail;
}
pPackedObject = nvswitch_os_malloc(INFOROM_DEM_OBJECT_V1_00_PACKED_SIZE);
if (pPackedObject == NULL)
{
status = -NVL_NO_MEM;
goto nvswitch_inforom_dem_load_fail;
}
status = nvswitch_inforom_load_object(device, pInforom, "DEM",
INFOROM_DEM_OBJECT_V1_00_FMT,
pPackedObject,
pFifo);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR, "Failed to load DEM object, rc: %d\n",
status);
goto nvswitch_inforom_dem_load_fail;
}
nvswitch_inforom_dem_load_fail:
if (pPackedObject)
{
nvswitch_os_free(pPackedObject);
}
//
// Mark the cached DEM as usable for Xid logging, even if we were
// unable to find it in the InfoROM image.
//
device->pSmbpbi->sharedSurface->inforomObjects.DEM.bValid = NV_TRUE;
_smbpbiDemInit(device, device->pSmbpbi, pFifo);
return status;
}
/*!
* Validate/Initialize the Driver Event Message (SXid) FIFO buffer
*
* @param[in] device device object pointer
* @param[in] pSmbpbi SMBPBI object pointer
* @param[in,out] pFifo DEM object pointer
*
* @return void
*/
static void
_smbpbiDemInit
(
nvswitch_device *device,
struct smbpbi *pSmbpbi,
struct INFOROM_DEM_OBJECT_V1_00 *pFifo
)
{
NvU8 msgLeft;
unsigned recordsHeld = 0;
NvU16 FIFO_REC_LOOP_ITERATOR;
NvU16 bytesOccupied;
NvU16 bytesSeen;
NvBool status = NV_FALSE;
// validate the FIFO buffer
if ((DEM_FIFO_PTR(pFifo->writeOffset) != pFifo->writeOffset) ||
(DEM_FIFO_PTR(pFifo->readOffset) != pFifo->readOffset) ||
((pFifo->writeOffset % sizeof(NvU32)) != 0) ||
((pFifo->readOffset % sizeof(NvU32)) != 0))
{
goto smbpbiDemInit_exit;
}
if (pFifo->writeOffset == pFifo->readOffset)
{
// The FIFO is empty
status = NV_TRUE;
goto smbpbiDemInit_exit;
}
//
// This HAL extracts from a scratch register the count of DEM messages
// in the FIFO that has not yet been requested by the SMBPBI client.
// If the FIFO holds more messages than that, it means those in excess
// of this count have been delivered to the client by PreOS app.
//
if (device->hal.nvswitch_smbpbi_get_dem_num_messages(device, &msgLeft) != NVL_SUCCESS)
{
// assume the maximum
msgLeft = ~0;
}
if (msgLeft == 0)
{
// Nothing of value in the FIFO. Lets reset it explicitly.
status = NV_TRUE;
pFifo->writeOffset = 0;
pFifo->readOffset = 0;
goto smbpbiDemInit_exit;
}
//
// Count the messages in the FIFO, while also checking the structure
// for integrity. Reset the FIFO in case any corruption is found.
//
bytesOccupied = DEM_BYTES_OCCUPIED(pFifo);
bytesSeen = 0;
FIFO_REC_LOOP_START(pFifo, bytesSeen < bytesOccupied)
if ((_recSize > DEM_RECORD_SIZE_MAX) ||
(FIFO_REC_LOOP_REC_SIZE < DEM_RECORD_SIZE_MIN))
{
goto smbpbiDemInit_exit;
}
bytesSeen += FIFO_REC_LOOP_REC_SIZE;
++recordsHeld;
FIFO_REC_LOOP_END
if ((bytesSeen != bytesOccupied) || (msgLeft > recordsHeld))
{
goto smbpbiDemInit_exit;
}
//
// Advance the FIFO read ptr in order to remove those messages that
// have already been delivered to the client.
//
FIFO_REC_LOOP_START(pFifo, recordsHeld > msgLeft)
--recordsHeld;
FIFO_REC_LOOP_END
pFifo->readOffset = FIFO_REC_LOOP_ITERATOR;
status = NV_TRUE;
smbpbiDemInit_exit:
if (!status)
{
// Reset the FIFO
pFifo->writeOffset = 0;
pFifo->readOffset = 0;
pFifo->seqNumber = 0;
}
}
static void
_nvswitch_smbpbi_dem_flush(nvswitch_device *device)
{
NvU8 *pPackedObject = NULL;
struct INFOROM_DEM_OBJECT_V1_00 *pFifo;
NvlStatus status = NVL_SUCCESS;
pPackedObject = nvswitch_os_malloc(INFOROM_DEM_OBJECT_V1_00_PACKED_SIZE);
if (pPackedObject == NULL)
{
status = -NVL_NO_MEM;
goto _nvswitch_smbpbi_dem_flush_exit;
}
pFifo = GET_PFIFO_FROM_DEVICE(device);
status = nvswitch_inforom_write_object(device, "DEM",
INFOROM_DEM_OBJECT_V1_00_FMT,
pFifo,
pPackedObject);
_nvswitch_smbpbi_dem_flush_exit:
nvswitch_os_free(pPackedObject);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR, "DEM object write failed, status=%d\n",
status);
}
}
/*!
* A helper to create a new DEM FIFO record
*
* @param[in,out] pFifo DEM object pointer
* @param[in] num Xid number
* @param[in] osErrorString text message to store
* @param[in] msglen message size
* @param[out] pRecSize new record size in bytes
*
* @return ptr to the new record
* @return NULL if there's no room in the FIFO
* or dynamic allocation error
*/
static NV_MSGBOX_DEM_RECORD *
_makeNewRecord
(
INFOROM_DEM_OBJECT_V1_00 *pFifo,
NvU32 num,
NvU8 *osErrorString,
NvU32 msglen,
NvU32 *pRecSize
)
{
NV_MSGBOX_DEM_RECORD *pNewRec;
*pRecSize = NV_MIN(sizeof(NV_MSGBOX_DEM_RECORD) + msglen,
DEM_RECORD_SIZE_MAX);
if ((*pRecSize > DEM_BYTES_AVAILABLE(pFifo)) ||
((pNewRec = nvswitch_os_malloc(*pRecSize)) == NULL))
{
return NULL;
}
// Fill the new record.
nvswitch_os_memset(pNewRec, 0, *pRecSize);
pNewRec->recordSize = NV_UNSIGNED_DIV_CEIL(*pRecSize, sizeof(NvU32));
pNewRec->xidId = num;
pNewRec->seqNumber = pFifo->seqNumber++;
pNewRec->timeStamp = nvswitch_os_get_platform_time() / NVSWITCH_NSEC_PER_SEC;
if (msglen > NV_MSGBOX_MAX_DRIVER_EVENT_MSG_TXT_SIZE)
{
// The text string is too long. Truncate and notify the client.
pNewRec->flags = FLD_SET_DRF(_MSGBOX, _DEM_RECORD_FLAGS,
_TRUNC, _SET, pNewRec->flags);
msglen = NV_MSGBOX_MAX_DRIVER_EVENT_MSG_TXT_SIZE - 1;
}
nvswitch_os_memcpy(pNewRec->textMessage, osErrorString, msglen);
return pNewRec;
}
/*!
* A helper to add the new record to the DEM FIFO
*
* @param[in,out] pFifo DEM object pointer
* @param[in] pNewRec the new record
* @param[in] recSize new record size in bytes
*
* @return void
*/
static void
_addNewRecord
(
INFOROM_DEM_OBJECT_V1_00 *pFifo,
NV_MSGBOX_DEM_RECORD *pNewRec,
NvU32 recSize
)
{
NvU16 rem;
NvU16 curPtr;
NvU16 copySz;
NvU8 *srcPtr;
// Copy the new record into the FIFO, handling a possible wrap-around.
rem = recSize;
curPtr = pFifo->writeOffset;
srcPtr = (NvU8 *)pNewRec;
while (rem > 0)
{
copySz = NV_MIN(rem, DEM_FIFO_SIZE - curPtr);
nvswitch_os_memcpy(pFifo->fifoBuffer + curPtr, srcPtr, copySz);
rem -= copySz;
srcPtr += copySz;
curPtr = DEM_FIFO_PTR(curPtr + copySz);
}
// Advance the FIFO write ptr.
pFifo->writeOffset = DEM_FIFO_PTR(pFifo->writeOffset +
(pNewRec->recordSize * sizeof(NvU32)));
}
/*!
* Add a Driver Event Message (SXid) to the InfoROM DEM FIFO buffer
*
* @param[in] device device object pointer
* @param[in] num Xid number
* @param[in] msglen message size
* @param[in] osErrorString text message to store
*
* @return void
*/
void
nvswitch_smbpbi_log_message
(
nvswitch_device *device,
NvU32 num,
NvU32 msglen,
NvU8 *osErrorString
)
{
INFOROM_DEM_OBJECT_V1_00 *pFifo;
NvU32 recSize;
NvU16 FIFO_REC_LOOP_ITERATOR;
NV_MSGBOX_DEM_RECORD *pNewRec;
if ((device->pSmbpbi == NULL) ||
(device->pSmbpbi->sharedSurface == NULL))
{
return;
}
pFifo = GET_PFIFO_FROM_DEVICE(device);
pNewRec = _makeNewRecord(pFifo, num, osErrorString, msglen, &recSize);
if (pNewRec != NULL)
{
_addNewRecord(pFifo, pNewRec, recSize);
nvswitch_os_free(pNewRec);
}
else
{
//
// We are unable to log this message. Mark the latest record
// with a flag telling the client that message(s) were dropped.
//
NvU16 bytesOccupied = DEM_BYTES_OCCUPIED(pFifo);
NvU16 bytesSeen;
NV_MSGBOX_DEM_RECORD *pLastRec = NULL;
// Find the newest record
bytesSeen = 0;
FIFO_REC_LOOP_START(pFifo, bytesSeen < bytesOccupied)
pLastRec = FIFO_REC_LOOP_REC_PTR;
bytesSeen += FIFO_REC_LOOP_REC_SIZE;
FIFO_REC_LOOP_END
if (pLastRec != NULL)
{
pLastRec->flags = FLD_SET_DRF(_MSGBOX, _DEM_RECORD_FLAGS,
_OVFL, _SET, pLastRec->flags);
}
}
return;
}
NvlStatus
nvswitch_smbpbi_set_link_error_info
(
nvswitch_device *device,
NVSWITCH_LINK_TRAINING_ERROR_INFO *pLinkTrainingErrorInfo,
NVSWITCH_LINK_RUNTIME_ERROR_INFO *pLinkRuntimeErrorInfo
)
{
FLCN *pFlcn;
RM_FLCN_CMD_SOE cmd;
NVSWITCH_TIMEOUT timeout;
NvU32 cmdSeqDesc;
RM_SOE_SMBPBI_CMD_SET_LINK_ERROR_INFO *pSetCmd = &cmd.cmd.smbpbiCmd.linkErrorInfo;
NvlStatus status;
if (!device->pSmbpbi)
{
return -NVL_ERR_NOT_SUPPORTED;
}
pFlcn = device->pSoe->pFlcn;
nvswitch_os_memset(&cmd, 0, sizeof(cmd));
cmd.hdr.unitId = RM_SOE_UNIT_SMBPBI;
cmd.hdr.size = RM_SOE_CMD_SIZE(SMBPBI, SET_LINK_ERROR_INFO);
cmd.cmd.smbpbiCmd.cmdType = RM_SOE_SMBPBI_CMD_ID_SET_LINK_ERROR_INFO;
pSetCmd->trainingErrorInfo.isValid = pLinkTrainingErrorInfo->isValid;
pSetCmd->runtimeErrorInfo.isValid = pLinkRuntimeErrorInfo->isValid;
RM_FLCN_U64_PACK(&pSetCmd->trainingErrorInfo.attemptedTrainingMask0,
&pLinkTrainingErrorInfo->attemptedTrainingMask0);
RM_FLCN_U64_PACK(&pSetCmd->trainingErrorInfo.trainingErrorMask0,
&pLinkTrainingErrorInfo->trainingErrorMask0);
RM_FLCN_U64_PACK(&pSetCmd->runtimeErrorInfo.mask0, &pLinkRuntimeErrorInfo->mask0);
nvswitch_timeout_create(NVSWITCH_INTERVAL_1SEC_IN_NS, &timeout);
status = flcnQueueCmdPostBlocking(device, pFlcn,
(PRM_FLCN_CMD)&cmd,
NULL, // pMsg - not used for now
NULL, // pPayload - not used for now
SOE_RM_CMDQ_LOG_ID,
&cmdSeqDesc,
&timeout);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR, "%s SMBPBI Set Link Error Info command failed. rc:%d\n",
__FUNCTION__, status);
return status;
}
return NVL_SUCCESS;
}