550.40.07

This commit is contained in:
Bernhard Stoeckner
2024-01-24 17:51:53 +01:00
parent bb2dac1f20
commit 91676d6628
1411 changed files with 261367 additions and 145959 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -279,6 +279,7 @@ _flcnDbgInfoCaptureRiscvPcTrace_LS10
{
NvU32 ctl, ridx, widx, bufferSize;
NvBool bWasFull;
NvU64 bios_version;
// Only supported on riscv
if (!UPROC_ENG_ARCH_FALCON_RISCV(pFlcn))
@@ -354,8 +355,13 @@ _flcnDbgInfoCaptureRiscvPcTrace_LS10
break;
}
NVSWITCH_PRINT(device, ERROR, "%s: TRACE[%d] = 0x%16llx\n", __FUNCTION__, entry, pc);
NVSWITCH_PRINT_SXID_NO_BBX(device, NVSWITCH_ERR_HW_SOE_HALT, "SOE HALT data[%d] = 0x%16llx\n", entry, pc);
}
// Print VBIOS version at the end
nvswitch_lib_get_bios_version(device, &bios_version);
NVSWITCH_PRINT_SXID_NO_BBX(device, NVSWITCH_ERR_HW_SOE_HALT,
"SOE HALT data[%d] = 0x%16llx\n", entry, bios_version);
}
// reset trace buffer

View File

@@ -0,0 +1,612 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2023 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 "nvlink_export.h"
#include "common_nvswitch.h"
#include "fsprpc_nvswitch.h"
#include "ls10/ls10.h"
#include "fsp/fsp_emem_channels.h"
#include "fsp/nvdm_payload_cmd_response.h"
#include "fsp/fsp_nvdm_format.h"
#include "fsp/fsp_mctp_format.h"
#include "fsp/fsp_tnvl_rpc.h"
#include "nvswitch/ls10/dev_fsp_pri.h"
/*!
* @brief Update command queue head and tail pointers
*
* @param[in] device nvswitch device pointer
* @param[in] queueHead Offset to write to command queue head
* @param[in] queueTail Offset to write to command queue tail
*/
void
nvswitch_fsp_update_cmdq_head_tail_ls10
(
nvswitch_device *device,
NvU32 queueHead,
NvU32 queueTail
)
{
// The write to HEAD needs to happen after TAIL because it will interrupt FSP
NVSWITCH_REG_WR32(device, _PFSP, _QUEUE_TAIL(FSP_EMEM_CHANNEL_RM), queueTail);
NVSWITCH_REG_WR32(device, _PFSP, _QUEUE_HEAD(FSP_EMEM_CHANNEL_RM), queueHead);
}
/*!
* @brief Read command queue head and tail pointers
*
* @param[in] device nvswitch device pointer
* @param[out] pQueueHead Pointer where we write command queue head
* @param[out] pQueueTail Pointer where we write command queue tail
*/
void
nvswitch_fsp_get_cmdq_head_tail_ls10
(
nvswitch_device *device,
NvU32 *pQueueHead,
NvU32 *pQueueTail
)
{
*pQueueHead = NVSWITCH_REG_RD32(device, _PFSP, _QUEUE_HEAD(FSP_EMEM_CHANNEL_RM));
*pQueueTail = NVSWITCH_REG_RD32(device, _PFSP, _QUEUE_TAIL(FSP_EMEM_CHANNEL_RM));
}
/*!
* @brief Update message queue head and tail pointers
*
* @param[in] device nvswitch device pointer
* @param[in] msgqHead Offset to write to message queue head
* @param[in] msgqTail Offset to write to message queue tail
*/
void
nvswitch_fsp_update_msgq_head_tail_ls10
(
nvswitch_device *device,
NvU32 msgqHead,
NvU32 msgqTail
)
{
NVSWITCH_REG_WR32(device, _PFSP, _MSGQ_TAIL(FSP_EMEM_CHANNEL_RM), msgqTail);
NVSWITCH_REG_WR32(device, _PFSP, _MSGQ_HEAD(FSP_EMEM_CHANNEL_RM), msgqHead);
}
/*!
* @brief Read message queue head and tail pointers
*
* @param[in] device nvswitch device pointer
* @param[out] pMsgqHead Pointer where we write message queue head
* @param[out] pMsgqTail Pointer where we write message queue tail
*/
void
nvswitch_fsp_get_msgq_head_tail_ls10
(
nvswitch_device *device,
NvU32 *pMsgqHead,
NvU32 *pMsgqTail
)
{
*pMsgqHead = NVSWITCH_REG_RD32(device, _PFSP, _MSGQ_HEAD(FSP_EMEM_CHANNEL_RM));
*pMsgqTail = NVSWITCH_REG_RD32(device, _PFSP, _MSGQ_TAIL(FSP_EMEM_CHANNEL_RM));
}
/*!
* @brief Get size of RM's channel in FSP EMEM
*
* @param[in] device nvswitch device pointer
*
* @return RM channel size in bytes
*/
NvU32
nvswitch_fsp_get_channel_size_ls10
(
nvswitch_device *device
)
{
//
// Channel size is hardcoded to 1K for now. Later we will use EMEMR to
// properly fetch the lower and higher bounds of the EMEM channel
//
return FSP_EMEM_CHANNEL_RM_SIZE;
}
/*!
* @brief Retreive SEID based on NVDM type
*
* For now, SEIDs are only needed for use-cases that send multi-packet RM->FSP
* messages. The SEID is used in these cases to route packets to the correct
* task as FSP receives them. Single-packet use-cases are given SEID 0.
*
* @param[in] device nvswitch device pointer
* @param[in] nvdmType NVDM message type
*
* @return SEID corresponding to passed-in NVDM type
*/
NvU8
nvswitch_fsp_nvdm_to_seid_ls10
(
nvswitch_device *device,
NvU8 nvdmType
)
{
NvU8 seid;
switch (nvdmType)
{
case NVDM_TYPE_INFOROM:
seid = 1;
break;
case NVDM_TYPE_HULK:
default:
seid = 0;
break;
}
return seid;
}
/*!
* @brief Create MCTP header
*
* @param[in] device nvswitch_device pointer
* @param[in] som Start of Message flag
* @param[in] eom End of Message flag
* @param[in] tag Message tag
* @param[in] seq Packet sequence number
*
* @return Constructed MCTP header
*/
NvU32
nvswitch_fsp_create_mctp_header_ls10
(
nvswitch_device *device,
NvU8 som,
NvU8 eom,
NvU8 seid,
NvU8 seq
)
{
return (REF_NUM(MCTP_HEADER_SOM, (som)) |
REF_NUM(MCTP_HEADER_EOM, (eom)) |
REF_NUM(MCTP_HEADER_SEID, (seid)) |
REF_NUM(MCTP_HEADER_SEQ, (seq)));
}
/*!
* @brief Create NVDM payload header
*
* @param[in] device nvswitch_device pointer
* @param[in] nvdmType NVDM type to include in header
*
* @return Constructed NVDM payload header
*/
NvU32
nvswitch_fsp_create_nvdm_header_ls10
(
nvswitch_device *device,
NvU32 nvdmType
)
{
return (REF_DEF(MCTP_MSG_HEADER_TYPE, _VENDOR_PCI) |
REF_DEF(MCTP_MSG_HEADER_VENDOR_ID, _NV) |
REF_NUM(MCTP_MSG_HEADER_NVDM_TYPE, (nvdmType)));
}
/*!
* @brief Retrieve and validate info in packet's MCTP headers
*
* @param[in] device nvswitch device pointer
* @param[in] pBuffer Buffer containing packet
* @param[in] size Size of buffer in bytes
* @param[out] pPacketState Pointer where we write packet state
* @param[out] pTag Pointer where we write packet's MCTP tag
*
* @return NVL_SUCCESS or NV_ERR_INVALID_DATA
*/
NvlStatus
nvswitch_fsp_get_packet_info_ls10
(
nvswitch_device *device,
NvU8 *pBuffer,
NvU32 size,
NvU8 *pPacketState,
NvU8 *pTag
)
{
NvU32 mctpHeader;
NvU8 som, eom;
NvlStatus status = NVL_SUCCESS;
mctpHeader = ((NvU32 *)pBuffer)[0];
som = REF_VAL(MCTP_HEADER_SOM, mctpHeader);
eom = REF_VAL(MCTP_HEADER_EOM, mctpHeader);
if ((som == 1) && (eom == 0))
{
*pPacketState = MCTP_PACKET_STATE_START;
}
else if ((som == 0) && (eom == 1))
{
*pPacketState = MCTP_PACKET_STATE_END;
}
else if ((som == 1) && (eom == 1))
{
*pPacketState = MCTP_PACKET_STATE_SINGLE_PACKET;
}
else
{
*pPacketState = MCTP_PACKET_STATE_INTERMEDIATE;
}
if ((*pPacketState == MCTP_PACKET_STATE_START) ||
(*pPacketState == MCTP_PACKET_STATE_SINGLE_PACKET))
{
// Packet contains payload header, check it
status = nvswitch_fsp_validate_mctp_payload_header(device, pBuffer, size);
}
*pTag = REF_VAL(MCTP_HEADER_TAG, mctpHeader);
return status;
}
/*!
* @brief Validate packet's MCTP payload header
*
* @param[in] device nvswitch device pointer
* @param[in] pBuffer Buffer containing packet
* @param[in] size Size of buffer in bytes
*
* @return NVL_SUCCESS or NV_ERR_INVALID_DATA
*/
NvlStatus
nvswitch_fsp_validate_mctp_payload_header_ls10
(
nvswitch_device *device,
NvU8 *pBuffer,
NvU32 size
)
{
NvU32 mctpPayloadHeader;
NvU16 mctpVendorId;
NvU8 mctpMessageType;
mctpPayloadHeader = ((NvU32 *)pBuffer)[1];
mctpMessageType = REF_VAL(MCTP_MSG_HEADER_TYPE, mctpPayloadHeader);
if (mctpMessageType != MCTP_MSG_HEADER_TYPE_VENDOR_PCI)
{
NVSWITCH_PRINT(device, ERROR, "Invalid MCTP Message type 0x%0x, expecting 0x7e (Vendor Defined PCI)\n",
mctpMessageType);
return -NVL_ERR_INVALID_STATE ;
}
mctpVendorId = REF_VAL(MCTP_MSG_HEADER_VENDOR_ID, mctpPayloadHeader);
if (mctpVendorId != MCTP_MSG_HEADER_VENDOR_ID_NV)
{
NVSWITCH_PRINT(device, ERROR, "Invalid PCI Vendor Id 0x%0x, expecting 0x10de (Nvidia)\n",
mctpVendorId);
return -NVL_ERR_INVALID_STATE ;
}
if (size < (sizeof(MCTP_HEADER) + sizeof(NvU8)))
{
NVSWITCH_PRINT(device, ERROR, "Packet doesn't contain NVDM type in payload header\n");
return -NVL_ERR_INVALID_STATE ;
}
return NVL_SUCCESS;
}
/*!
* @brief Process NVDM payload
*
* @param[in] device nvswitch device pointer
* @param[in] pBuffer Buffer containing packet data
* @param[in] Size Buffer size
*
* @return NVL_SUCCESS or NV_ERR_NOT_SUPPORTED
*/
NvlStatus
nvswitch_fsp_process_nvdm_msg_ls10
(
nvswitch_device *device,
NvU8 *pBuffer,
NvU32 size
)
{
NvU8 nvdmType;
NvlStatus status = NVL_SUCCESS;
nvdmType = pBuffer[0];
switch (nvdmType)
{
case NVDM_TYPE_FSP_RESPONSE:
status = nvswitch_fsp_process_cmd_response(device, pBuffer, size);
break;
default:
NVSWITCH_PRINT(device, ERROR, "Unknown or unsupported NVDM type received: 0x%0x\n",
nvdmType);
status = -NVL_ERR_NOT_SUPPORTED;
break;
}
return status;
}
/*!
* @brief Process FSP command response
*
* @param[in] device nvswitch device pointer
* @param[in] pBuffer Buffer containing packet data
* @param[in] Size Buffer size
*
* @return NVL_SUCCESS or -NVL_ERR_INVALID_STATE
*/
NvlStatus
nvswitch_fsp_process_cmd_response_ls10
(
nvswitch_device *device,
NvU8 *pBuffer,
NvU32 size
)
{
NVDM_PAYLOAD_COMMAND_RESPONSE *pCmdResponse;
NvU32 headerSize = sizeof(NvU8); // NVDM type
NvlStatus status = NVL_SUCCESS;
if (size < (headerSize + sizeof(NVDM_PAYLOAD_COMMAND_RESPONSE)))
{
NVSWITCH_PRINT(device, ERROR, "Expected FSP command response, but packet is not big enough for payload. Size: 0x%0x\n", size);
return -NVL_ERR_INVALID_STATE;
}
pCmdResponse = (NVDM_PAYLOAD_COMMAND_RESPONSE *)&(pBuffer[1]);
NVSWITCH_PRINT(device, INFO, "Received FSP command response. Task ID: 0x%0x Command type: 0x%0x Error code: 0x%0x\n",
pCmdResponse->taskId, pCmdResponse->commandNvdmType, pCmdResponse->errorCode);
status = nvswitch_fsp_error_code_to_nvlstatus_map(device, pCmdResponse->errorCode);
if (status == NVL_SUCCESS)
{
NVSWITCH_PRINT(device, INFO, "Last command was processed by FSP successfully!\n");
}
else if (status != -NVL_NOT_FOUND)
{
NVSWITCH_PRINT(device, ERROR, "FSP response reported error. Task ID: 0x%0x Command type: 0x%0x Error code: 0x%0x\n",
pCmdResponse->taskId, pCmdResponse->commandNvdmType, pCmdResponse->errorCode);
}
return status;
}
/*!
* @brief Configure EMEMC for RM's queue in FSP EMEM
*
* @param[in] device nvswitch device pointer
* @param[in] offset Offset to write to EMEMC in DWORDS
* @param[in] bAincw Flag to set auto-increment on writes
* @param[in] bAincr Flag to set auto-increment on reads
*
* @return NVL_SUCCESS
*/
NvlStatus
nvswitch_fsp_config_ememc_ls10
(
nvswitch_device *device,
NvU32 offset,
NvBool bAincw,
NvBool bAincr
)
{
NvU32 offsetBlks, offsetDwords;
NvU32 reg32 = 0;
//
// EMEMC offset is encoded in terms of blocks (64 DWORDS) and DWORD offset
// within a block, so calculate each.
//
offsetBlks = offset / 64;
offsetDwords = offset % 64;
reg32 = FLD_SET_DRF_NUM(_PFSP, _EMEMC, _OFFS, offsetDwords, reg32);
reg32 = FLD_SET_DRF_NUM(_PFSP, _EMEMC, _BLK, offsetBlks, reg32);
if (bAincw)
{
reg32 = FLD_SET_DRF(_PFSP, _EMEMC, _AINCW, _TRUE, reg32);
}
if (bAincr)
{
reg32 = FLD_SET_DRF(_PFSP, _EMEMC, _AINCR, _TRUE, reg32);
}
NVSWITCH_REG_WR32(device, _PFSP, _EMEMC(FSP_EMEM_CHANNEL_RM), reg32);
return NVL_SUCCESS;
}
/*!
* @brief Write data in buffer to RM channel in FSP's EMEM
*
* @param[in] device nvswitch device pointer
* @param[in] pBuffer Buffer with data to write to EMEM
* @param[in] Size Size of buffer in bytes, assumed DWORD aligned
*
* @return NVL_SUCCESS
*/
NvlStatus
nvswitch_fsp_write_to_emem_ls10
(
nvswitch_device *device,
NvU8 *pBuffer,
NvU32 size
)
{
NvU32 i, reg32;
NvU32 ememOffsetEnd;
//
// First configure EMEMC, RM always writes 0 to the offset, which is OK
// because RM's channel starts at 0 on GH100 and we always start from the
// beginning for each packet. It should be improved later to use EMEMR to
// properly fetch the lower and higher bounds of the EMEM channel
//
nvswitch_fsp_config_ememc(device, 0, NV_TRUE, NV_FALSE);
NVSWITCH_PRINT(device, INFO, "About to send data to FSP, ememcOff=0, size=0x%x\n", size);
if (!NV_IS_ALIGNED(size, sizeof(NvU32)))
{
NVSWITCH_PRINT(device, WARN, "Size=0x%x is not DWORD-aligned, data will be truncated!\n", size);
}
// Now write to EMEMD
for (i = 0; i < (size / 4); i++)
{
NVSWITCH_REG_WR32(device, _PFSP, _EMEMD(FSP_EMEM_CHANNEL_RM), ((NvU32*)(void*)pBuffer)[i]);
}
// Sanity check offset. If this fails, the autoincrement did not work
reg32 = NVSWITCH_REG_RD32(device, _PFSP, _EMEMC(FSP_EMEM_CHANNEL_RM));
ememOffsetEnd = DRF_VAL(_PFSP, _EMEMC, _OFFS, reg32);
// Blocks are 64 DWORDS
ememOffsetEnd += DRF_VAL(_PFSP, _EMEMC, _BLK, reg32) * 64;
NVSWITCH_PRINT(device, INFO, "After sending data, ememcOff = 0x%x\n", ememOffsetEnd);
NVSWITCH_ASSERT((ememOffsetEnd) == (size / sizeof(NvU32)));
return NVL_SUCCESS;
}
/*!
* @brief Read data to buffer from RM channel in FSP's EMEM
*
* @param[in] device nvswitch_device pointer
* @param[in/out] pBuffer Buffer where we copy data from EMEM
* @param[in] size Size to read in bytes, assumed DWORD aligned
*
* @return NVL_SUCCESS
*/
NvlStatus
nvswitch_fsp_read_from_emem_ls10
(
nvswitch_device *device,
NvU8 *pBuffer,
NvU32 size
)
{
NvU32 i, reg32;
NvU32 ememOffsetEnd;
//
// First configure EMEMC, RM always writes 0 to the offset, which is OK
// because RM's channel starts at 0 on GH100 and we always start from the
// beginning for each packet. It should be improved later to use EMEMR to
// properly fetch the lower and higher bounds of the EMEM channel
//
nvswitch_fsp_config_ememc(device, 0, NV_FALSE, NV_TRUE);
NVSWITCH_PRINT(device, INFO, "About to read data from FSP, ememcOff=0, size=0x%x\n", size);
if (!NV_IS_ALIGNED(size, sizeof(NvU32)))
{
NVSWITCH_PRINT(device, WARN, "Size=0x%x is not DWORD-aligned, data will be truncated!\n", size);
}
// Now read from EMEMD
for (i = 0; i < (size / 4); i++)
{
((NvU32*)(void*)pBuffer)[i] = NVSWITCH_REG_RD32(device, _PFSP, _EMEMD(FSP_EMEM_CHANNEL_RM));
}
// Sanity check offset. If this fails, the autoincrement did not work
reg32 = NVSWITCH_REG_RD32(device, _PFSP, _EMEMC(FSP_EMEM_CHANNEL_RM));
ememOffsetEnd = DRF_VAL(_PFSP, _EMEMC, _OFFS, reg32);
// Blocks are 64 DWORDS
ememOffsetEnd += DRF_VAL(_PFSP, _EMEMC, _BLK, reg32) * 64;
NVSWITCH_PRINT(device, INFO, "After reading data, ememcOff = 0x%x\n", ememOffsetEnd);
NVSWITCH_ASSERT((ememOffsetEnd) == (size / sizeof(NvU32)));
return NVL_SUCCESS;
}
NvlStatus
nvswitch_fsp_error_code_to_nvlstatus_map_ls10
(
nvswitch_device *device,
NvU32 errorCode
)
{
switch (errorCode)
{
case FSP_OK:
return NVL_SUCCESS;
case FSP_ERR_IFR_FILE_NOT_FOUND:
return -NVL_NOT_FOUND;
case FSP_ERR_IFS_ERR_INVALID_STATE:
case FSP_ERR_IFS_ERR_INVALID_DATA:
return -NVL_ERR_INVALID_STATE;
default:
return -NVL_ERR_GENERIC;
}
}
NvlStatus
nvswitch_fsprpc_get_caps_ls10
(
nvswitch_device *device,
NVSWITCH_FSPRPC_GET_CAPS_PARAMS *params
)
{
TNVL_RPC_CAPS_PAYLOAD payload;
TNVL_RPC_CAPS_RSP_PAYLOAD responsePayload;
NvlStatus status;
payload.subMessageId = TNVL_CAPS_SUBMESSAGE_ID;
nvswitch_os_memset(&responsePayload, 0, sizeof(TNVL_RPC_CAPS_RSP_PAYLOAD));
status = nvswitch_fsp_send_and_read_message(device,
(NvU8*) &payload, sizeof(TNVL_RPC_CAPS_PAYLOAD), NVDM_TYPE_CAPS_QUERY,
(NvU8*) &responsePayload, sizeof(TNVL_RPC_CAPS_RSP_PAYLOAD));
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR, "RPC failed for FSP caps query\n");
return status;
}
params->responseNvdmType = responsePayload.nvdmType;
params->commandNvdmType = responsePayload.cmdResponse.commandNvdmType;
params->errorCode = responsePayload.cmdResponse.errorCode;
params->pRspPayload = responsePayload.rspPayload;
return NVL_SUCCESS;
}

View File

@@ -0,0 +1,86 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2023 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 "common_nvswitch.h"
#include "error_nvswitch.h"
#include "export_nvswitch.h"
#include "ls10/soe_ls10.h"
#include "soe/soeifheartbeat.h"
/*!
* @brief Callback function to recieve Heartbeat messages from SOE.
*/
void
nvswitch_heartbeat_soe_callback_ls10
(
nvswitch_device *device,
RM_FLCN_MSG *pGenMsg,
void *pParams,
NvU32 seqDesc,
NV_STATUS status
)
{
RM_FLCN_MSG_SOE *pMsg = (RM_FLCN_MSG_SOE *)pGenMsg;
switch (pMsg->msg.heartbeat.msgType)
{
case RM_SOE_HEARTBEAT_MSG_ID_OSFP_THERM_WARN_ACTIVATED:
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_OSFP_THERM_WARN_ACTIVATED,
"OSFP Thermal Warn Activated\n");
break;
}
case RM_SOE_HEARTBEAT_MSG_ID_OSFP_THERM_WARN_DEACTIVATED:
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_OSFP_THERM_WARN_DEACTIVATED,
"OSFP Thermal Warn Deactivated\n");
break;
}
case RM_SOE_HEARTBEAT_MSG_ID_OSFP_THERM_OVERT_ACTIVATED:
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_OSFP_THERM_OVERT_ACTIVATED,
"OSFP Thermal Overt Activated\n");
break;
}
case RM_SOE_HEARTBEAT_MSG_ID_OSFP_THERM_OVERT_DEACTIVATED:
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_OSFP_THERM_OVERT_DEACTIVATED,
"OSFP Thermal Overt Deactivated\n");
break;
}
case RM_SOE_HEARTBEAT_MSG_ID_OSFP_THERM_HEARTBEAT_SHUTDOWN:
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_OSFP_THERM_HEARTBEAT_SHUTDOWN,
"OSFP Thermal SOE Heartbeat Shutdown\n");
break;
}
default:
{
NVSWITCH_PRINT(device, ERROR, "%s Unknown message Id\n", __FUNCTION__);
NVSWITCH_ASSERT(0);
}
}
}

View File

@@ -25,6 +25,7 @@
#include "intr_nvswitch.h"
#include "regkey_nvswitch.h"
#include "soe/soe_nvswitch.h"
#include "cci/cci_nvswitch.h"
#include "ls10/ls10.h"
#include "ls10/minion_ls10.h"
@@ -1264,12 +1265,12 @@ _nvswitch_service_route_fatal_ls10
if (nvswitch_is_soe_supported(device))
{
nvswitch_soe_disable_nport_fatal_interrupts_ls10(device, link,
report.raw_enable ^ pending, RM_SOE_CORE_NPORT_ROUTE_INTERRUPT);
report.raw_enable & ~pending, RM_SOE_CORE_NPORT_ROUTE_INTERRUPT);
}
else
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _ROUTE, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
}
@@ -1478,7 +1479,7 @@ _nvswitch_service_route_nonfatal_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _ROUTE, _ERR_NON_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -1743,12 +1744,12 @@ _nvswitch_service_ingress_fatal_ls10
if (nvswitch_is_soe_supported(device))
{
nvswitch_soe_disable_nport_fatal_interrupts_ls10(device, link,
report.raw_enable ^ pending, RM_SOE_CORE_NPORT_INGRESS_INTERRUPT);
report.raw_enable & ~pending, RM_SOE_CORE_NPORT_INGRESS_INTERRUPT);
}
else
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _INGRESS, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
}
@@ -2046,7 +2047,7 @@ _nvswitch_service_ingress_nonfatal_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _INGRESS, _ERR_NON_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -2189,7 +2190,7 @@ _nvswitch_service_ingress_nonfatal_ls10_err_status_1:
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _INGRESS, _ERR_NON_FATAL_REPORT_EN_1,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -2329,7 +2330,7 @@ _nvswitch_service_tstate_nonfatal_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _TSTATE, _ERR_NON_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -2519,12 +2520,12 @@ _nvswitch_service_tstate_fatal_ls10
if (nvswitch_is_soe_supported(device))
{
nvswitch_soe_disable_nport_fatal_interrupts_ls10(device, link,
report.raw_enable ^ pending, RM_SOE_CORE_NPORT_TSTATE_INTERRUPT);
report.raw_enable & ~pending, RM_SOE_CORE_NPORT_TSTATE_INTERRUPT);
}
else
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _TSTATE, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
}
@@ -2653,7 +2654,7 @@ _nvswitch_service_egress_nonfatal_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _EGRESS, _ERR_NON_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -2898,7 +2899,7 @@ _nvswitch_service_egress_nonfatal_ls10_err_status_1:
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _EGRESS, _ERR_NON_FATAL_REPORT_EN_1,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -3175,12 +3176,12 @@ _nvswitch_service_egress_fatal_ls10
if (nvswitch_is_soe_supported(device))
{
nvswitch_soe_disable_nport_fatal_interrupts_ls10(device, link,
report.raw_enable ^ pending, RM_SOE_CORE_NPORT_EGRESS_0_INTERRUPT);
report.raw_enable & ~pending, RM_SOE_CORE_NPORT_EGRESS_0_INTERRUPT);
}
else
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _EGRESS, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
}
@@ -3306,12 +3307,12 @@ _nvswitch_service_egress_fatal_ls10_err_status_1:
if (nvswitch_is_soe_supported(device))
{
nvswitch_soe_disable_nport_fatal_interrupts_ls10(device, link,
report.raw_enable ^ pending, RM_SOE_CORE_NPORT_EGRESS_1_INTERRUPT);
report.raw_enable & ~pending, RM_SOE_CORE_NPORT_EGRESS_1_INTERRUPT);
}
else
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _EGRESS, _ERR_FATAL_REPORT_EN_1,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
}
@@ -3410,7 +3411,7 @@ _nvswitch_service_sourcetrack_nonfatal_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _SOURCETRACK, _ERR_NON_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -3538,12 +3539,12 @@ _nvswitch_service_sourcetrack_fatal_ls10
if (nvswitch_is_soe_supported(device))
{
nvswitch_soe_disable_nport_fatal_interrupts_ls10(device, link,
report.raw_enable ^ pending, RM_SOE_CORE_NPORT_SOURCETRACK_INTERRUPT);
report.raw_enable & ~pending, RM_SOE_CORE_NPORT_SOURCETRACK_INTERRUPT);
}
else
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _SOURCETRACK, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
}
@@ -3690,7 +3691,7 @@ _nvswitch_service_multicast_nonfatal_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _MULTICASTTSTATE, _ERR_NON_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -3830,12 +3831,12 @@ _nvswitch_service_multicast_fatal_ls10
if (nvswitch_is_soe_supported(device))
{
nvswitch_soe_disable_nport_fatal_interrupts_ls10(device, link,
report.raw_enable ^ pending, RM_SOE_CORE_NPORT_MULTICAST_INTERRUPT);
report.raw_enable & ~pending, RM_SOE_CORE_NPORT_MULTICAST_INTERRUPT);
}
else
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _MULTICASTTSTATE, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
}
@@ -3976,7 +3977,7 @@ _nvswitch_service_reduction_nonfatal_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _REDUCTIONTSTATE, _ERR_NON_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -4131,12 +4132,12 @@ _nvswitch_service_reduction_fatal_ls10
if (nvswitch_is_soe_supported(device))
{
nvswitch_soe_disable_nport_fatal_interrupts_ls10(device, link,
report.raw_enable ^ pending, RM_SOE_CORE_NPORT_REDUCTION_INTERRUPT);
report.raw_enable & ~pending, RM_SOE_CORE_NPORT_REDUCTION_INTERRUPT);
}
else
{
NVSWITCH_ENG_WR32(device, NPORT, , link, _REDUCTIONTSTATE, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
}
@@ -4534,7 +4535,7 @@ _nvswitch_service_nvltlc_tx_sys_fatal_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_LINK_WR32_LS10(device, link, NVLTLC, _NVLTLC_TX_SYS, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
NVSWITCH_LINK_WR32_LS10(device, link, NVLTLC, _NVLTLC_TX_SYS, _ERR_STATUS_0, pending);
@@ -4654,7 +4655,7 @@ _nvswitch_service_nvltlc_rx_sys_fatal_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_LINK_WR32_LS10(device, link, NVLTLC, _NVLTLC_RX_SYS, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
NVSWITCH_LINK_WR32_LS10(device, link, NVLTLC, _NVLTLC_RX_SYS, _ERR_STATUS_0, pending);
@@ -4755,7 +4756,7 @@ _nvswitch_service_nvltlc_tx_lnk_fatal_0_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_LINK_WR32_LS10(device, link, NVLTLC, _NVLTLC_TX_LNK, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -4942,7 +4943,7 @@ _nvswitch_service_nvltlc_rx_lnk_fatal_0_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_LINK_WR32_LS10(device, link, NVLTLC, _NVLTLC_RX_LNK, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -5045,7 +5046,7 @@ _nvswitch_service_nvltlc_rx_lnk_fatal_1_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_LINK_WR32_LS10(device, link, NVLTLC, _NVLTLC_RX_LNK, _ERR_FATAL_REPORT_EN_1,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -5208,7 +5209,7 @@ _nvswitch_service_nvlipt_common_fatal_ls10
(device->link[link].fatal_error_occurred))
{
NVSWITCH_ENG_WR32(device, NVLIPT, , instance, _NVLIPT_COMMON, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
break;
}
}
@@ -5331,7 +5332,7 @@ _nvswitch_service_nxbar_tile_ls10
// Disable interrupts that have occurred after fatal error.
// This helps prevent an interrupt storm if HW keeps triggering unnecessary stream of interrupts.
NVSWITCH_TILE_WR32(device, tile, _NXBAR_TILE, _ERR_FATAL_INTR_EN,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
NVSWITCH_TILE_WR32(device, link, _NXBAR_TILE, _ERR_STATUS, pending);
@@ -5435,7 +5436,7 @@ _nvswitch_service_nxbar_tileout_ls10
// Disable interrupts that have occurred after fatal error.
// This helps prevent an interrupt storm if HW keeps triggering unnecessary stream of interrupts.
NVSWITCH_TILEOUT_WR32(device, tileout, _NXBAR_TILEOUT, _ERR_FATAL_INTR_EN,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
NVSWITCH_TILEOUT_WR32(device, tileout, _NXBAR_TILEOUT, _ERR_STATUS, pending);
@@ -5838,6 +5839,12 @@ _nvswitch_deferred_link_state_check_ls10
chip_device->deferredLinkErrors[link].state.bLinkStateCallBackEnabled = NV_FALSE;
bRedeferLinkStateCheck = NV_FALSE;
// Ask CCI if link state check should be futher deferred
if (cciIsLinkManaged(device, link) && !cciReportLinkErrors(device, link))
{
bRedeferLinkStateCheck = NV_TRUE;
}
// Link came up after last retrain
if (lastLinkUpTime >= lastRetrainTime)
{
@@ -6310,7 +6317,7 @@ _nvswitch_service_nvltlc_tx_lnk_nonfatal_0_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_LINK_WR32(device, link, NVLTLC, _NVLTLC_TX_LNK, _ERR_NON_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -6532,7 +6539,7 @@ _nvswitch_service_nvltlc_tx_lnk_nonfatal_1_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_LINK_WR32(device, link, NVLTLC, _NVLTLC_TX_LNK, _ERR_NON_FATAL_REPORT_EN_1,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (report.raw_first & report.mask)
@@ -7103,7 +7110,7 @@ _nvswitch_service_nvlipt_lnk_fatal_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_LINK_WR32(device, link, NVLIPT_LNK, _NVLIPT_LNK, _ERR_FATAL_REPORT_EN_0,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
// clear interrupts
@@ -7768,16 +7775,29 @@ nvswitch_service_nvldl_fatal_link_ls10
NVSWITCH_PRINT(device, ERROR, "%s: Failed to notify PORT_DOWN event\n",
__FUNCTION__);
}
dlDeferredIntrLinkMask |= bit;
dlDeferredIntrLinkMask |= bit;
//
// Disable LTSSM FAULT DOWN, NPG, and NVLW interrupts to avoid interrupt storm. The interrupts
// will be re-enabled in reset and drain
//
report.raw_enable = FLD_SET_DRF(_NVLDL_TOP, _INTR_STALL_EN, _LTSSM_FAULT_DOWN, _DISABLE, report.raw_enable);
NVSWITCH_LINK_WR32(device, link, NVLDL, _NVLDL_TOP, _INTR_STALL_EN, report.raw_enable);
nvswitch_link_disable_interrupts_ls10(device, link);
if (device->bModeContinuousALI)
{
//
// Since reset and drain will reset the link, including clearing
// pending interrupts, skip the clear write below. There are cases
// where link clocks will not be on after reset and drain so there
// maybe PRI errors on writing to the register
//
{
bRequireResetAndDrain = NV_TRUE;
// CCI will perform reset and drain
if (!cciIsLinkManaged(device, link))
{
bRequireResetAndDrain = NV_TRUE;
}
}
nvswitch_clear_flags(&unhandled, bit);
}
@@ -7792,25 +7812,41 @@ nvswitch_service_nvldl_fatal_link_ls10
NVSWITCH_PRINT(device, ERROR, "%s: Failed to notify PORT_DOWN event\n",
__FUNCTION__);
}
dlDeferredIntrLinkMask |= bit;
dlDeferredIntrLinkMask |= bit;
//
// Disable LTSSM FAULT UP, NPG, and NVLW link interrupts to avoid interrupt storm. The interrupts
// will be re-enabled in reset and drain
//
report.raw_enable = FLD_SET_DRF(_NVLDL_TOP, _INTR_STALL_EN, _LTSSM_FAULT_UP, _DISABLE, report.raw_enable);
NVSWITCH_LINK_WR32(device, link, NVLDL, _NVLDL_TOP, _INTR_STALL_EN, report.raw_enable);
nvswitch_link_disable_interrupts_ls10(device, link);
if (device->bModeContinuousALI)
{
//
// Since reset and drain will reset the link, including clearing
// pending interrupts, skip the clear write below. There are cases
// where link clocks will not be on after reset and drain so there
// maybe PRI errors on writing to the register
//
{
bRequireResetAndDrain = NV_TRUE;
// CCI will perform reset and drain
if (!cciIsLinkManaged(device, link))
{
bRequireResetAndDrain = NV_TRUE;
}
}
nvswitch_clear_flags(&unhandled, bit);
}
if (bRequireResetAndDrain)
{
chip_device->deferredLinkErrors[link].data.fatalIntrMask.dl |= dlDeferredIntrLinkMask;
device->hal.nvswitch_reset_and_drain_links(device, NVBIT64(link));
chip_device->deferredLinkErrors[link].state.lastRetrainTime = nvswitch_os_get_platform_time();
device->hal.nvswitch_reset_and_drain_links(device, NVBIT64(link), NV_FALSE);
}
chip_device->deferredLinkErrors[link].data.fatalIntrMask.dl |= dlDeferredIntrLinkMask;
if (dlDeferredIntrLinkMask)
{
nvswitch_create_deferred_link_state_check_task_ls10(device, nvlipt_instance, link);
}
@@ -7820,7 +7856,7 @@ nvswitch_service_nvldl_fatal_link_ls10
if (device->link[link].fatal_error_occurred)
{
NVSWITCH_LINK_WR32(device, link, NVLDL, _NVLDL_TOP, _INTR_STALL_EN,
report.raw_enable ^ pending);
report.raw_enable & ~pending);
}
if (!bRequireResetAndDrain)

View File

@@ -28,6 +28,7 @@
#include "regkey_nvswitch.h"
#include "ls10/ls10.h"
#include "nvswitch/ls10/dev_nvldl_ip_addendum.h"
#include "cci/cci_nvswitch.h"
#include "nvswitch/ls10/dev_nvldl_ip.h"
#include "nvswitch/ls10/dev_nvlipt_lnk_ip.h"
@@ -98,54 +99,52 @@ _nvswitch_configure_reserved_throughput_counters
DRF_DEF(_NVLTLC_TX_LNK, _DEBUG_TP_CNTR_CTRL_0, _ENABLE, _ENABLE));
}
void
nvswitch_program_l1_scratch_reg_ls10
(
nvswitch_device *device,
NvU32 linkNumber
)
{
NvU32 scrRegVal;
NvU32 tempRegVal;
// Read L1 register and store initial/VBIOS L1 Threshold Value in Scratch register
tempRegVal = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLIPT_LNK, _NVLIPT_LNK, _PWRM_L1_ENTER_THRESHOLD);
scrRegVal = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLIPT_LNK, _NVLIPT_LNK, _SCRATCH_WARM);
// Update the scratch register value only if it has not been written to before
if (scrRegVal == NV_NVLIPT_LNK_SCRATCH_WARM_DATA_INIT)
{
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLIPT_LNK, _NVLIPT_LNK, _SCRATCH_WARM, tempRegVal);
}
}
#define BUG_3797211_LS10_VBIOS_VERSION 0x9610410000
void
nvswitch_init_lpwr_regs_ls10
(
nvlink_link *link
)
{
nvswitch_device *device = link->dev->pDevInfo;
// NVSWITCH_BIOS_NVLINK_CONFIG *bios_config;
NvU32 linkNum = link->linkNumber;
NvU32 tempRegVal, lpEntryThreshold;
NvU8 softwareDesired;
NvBool bLpEnable;
NvlStatus status;
nvswitch_device *device;
if (IS_RTLSIM(device) || IS_EMULATION(device) || IS_FMODEL(device))
if (link == NULL)
{
return;
}
if (device->regkeys.enable_pm == NV_SWITCH_REGKEY_ENABLE_PM_NO)
device = link->dev->pDevInfo;
status = nvswitch_ctrl_set_link_l1_threshold_ls10(link, device->regkeys.lp_threshold);
if (status != NVL_SUCCESS)
{
return;
NVSWITCH_PRINT(device, ERROR, "%s: Failed to set L1 Threshold\n",
__FUNCTION__);
}
// bios_config = nvswitch_get_bios_nvlink_config(device);
// IC Enter Threshold
if (device->regkeys.lp_threshold == NV_SWITCH_REGKEY_SET_LP_THRESHOLD_DEFAULT)
{
//
// Do nothing since VBIOS sets the default L1 threshold.
// Refer Bug 3797211 for more info.
//
}
else
{
lpEntryThreshold = device->regkeys.lp_threshold;
tempRegVal = 0;
tempRegVal = FLD_SET_DRF_NUM(_NVLIPT, _LNK_PWRM_L1_ENTER_THRESHOLD, _THRESHOLD, lpEntryThreshold, tempRegVal);
NVSWITCH_LINK_WR32_LS10(device, linkNum, NVLIPT_LNK, _NVLIPT_LNK, _PWRM_L1_ENTER_THRESHOLD, tempRegVal);
}
//LP Entry Enable
bLpEnable = NV_TRUE;
softwareDesired = (bLpEnable) ? 0x1 : 0x0;
tempRegVal = NVSWITCH_LINK_RD32_LS10(device, linkNum, NVLIPT_LNK, _NVLIPT_LNK, _PWRM_CTRL);
tempRegVal = FLD_SET_DRF_NUM(_NVLIPT, _LNK_PWRM_CTRL, _L1_SOFTWARE_DESIRED, softwareDesired, tempRegVal);
NVSWITCH_LINK_WR32_LS10(device, linkNum, NVLIPT_LNK, _NVLIPT_LNK, _PWRM_CTRL, tempRegVal);
}
void
@@ -573,6 +572,15 @@ nvswitch_corelib_get_tl_link_mode_ls10
link_state = DRF_VAL(_NVLIPT_LNK, _CTRL_LINK_STATE_STATUS, _CURRENTLINKSTATE,
val);
if (cciIsLinkManaged(device, link->linkNumber))
{
if (link_state == NV_NVLIPT_LNK_CTRL_LINK_STATE_STATUS_CURRENTLINKSTATE_RESET)
{
*mode = NVLINK_LINKSTATE_RESET;
return NVL_SUCCESS;
}
}
switch(link_state)
{
case NV_NVLIPT_LNK_CTRL_LINK_STATE_STATUS_CURRENTLINKSTATE_ACTIVE:
@@ -1434,6 +1442,7 @@ nvswitch_load_link_disable_settings_ls10
if (FLD_TEST_DRF(_NVLIPT_LNK, _CTRL_LINK_STATE_STATUS, _CURRENTLINKSTATE, _DISABLE, regVal))
{
NVSWITCH_ASSERT(!cciIsLinkManaged(device, link->linkNumber));
// Set link to invalid and unregister from corelib
device->link[link->linkNumber].valid = NV_FALSE;
@@ -1544,6 +1553,12 @@ nvswitch_reset_and_train_link_ls10
nvswitch_execute_unilateral_link_shutdown_ls10(link);
nvswitch_corelib_clear_link_state_ls10(link);
// If link is CCI managed then return early
if (cciIsLinkManaged(device, link->linkNumber))
{
return NVL_SUCCESS;
}
//
// When a link faults there could be a race between the driver requesting
// reset and MINION processing Emergency Shutdown. Minion will notify if
@@ -1738,6 +1753,176 @@ nvswitch_request_tl_link_state_ls10
return status;
}
// Initialize optical links for pre-training
NvlStatus
nvswitch_cci_initialization_sequence_ls10
(
nvswitch_device *device,
NvU32 linkNumber
)
{
NvlStatus status;
nvlink_link link;
nvlink_device dev;
link.linkNumber = linkNumber;
link.dev = &dev;
link.dev->pDevInfo = device;
// Perform INITPHASE1
status = nvswitch_minion_send_command(device, linkNumber,
NV_MINION_NVLINK_DL_CMD_COMMAND_INITPHASE1, 0);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s : NV_MINION_NVLINK_DL_CMD_COMMAND_INITPHASE1 failed on link %d.\n",
__FUNCTION__, linkNumber);
return status;
}
// SET RX detect
status = nvswitch_minion_send_command(device, linkNumber,
NV_MINION_NVLINK_DL_CMD_COMMAND_TURING_RXDET, 0);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Set RXDET failed for link %d.\n",
__FUNCTION__, linkNumber);
return status;
}
// Enable Common mode on Tx
status = _nvswitch_init_dl_pll(&link);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to enable common mode for link %d.\n",
__FUNCTION__, linkNumber);
return status;
}
status = nvswitch_minion_send_command(device, linkNumber,
NV_MINION_NVLINK_DL_CMD_COMMAND_INITPHASE5A, 0);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s : NV_MINION_NVLINK_DL_CMD_COMMAND_INITPHASE5A failed on link %d.\n",
__FUNCTION__, linkNumber);
return status;
}
return NVL_SUCCESS;
}
NvlStatus
nvswitch_cci_deinitialization_sequence_ls10
(
nvswitch_device *device,
NvU32 linkNumber
)
{
NvlStatus status;
nvlink_link link;
nvlink_device dev;
link.linkNumber = linkNumber;
link.dev = &dev;
link.dev->pDevInfo = device;
// Perform ABORTRXDET
status = nvswitch_minion_send_command(device, linkNumber,
NV_MINION_NVLINK_DL_CMD_COMMAND_ABORTRXDET, 0);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s : NV_MINION_NVLINK_DL_CMD_COMMAND_ABORTRXDET failed on link %d.\n",
__FUNCTION__, linkNumber);
return status;
}
return NVL_SUCCESS;
}
NvlStatus
nvswitch_cci_enable_iobist_ls10
(
nvswitch_device *device,
NvU32 linkNumber,
NvBool bEnable
)
{
NvU32 val;
if (bEnable)
{
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIG);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _CONFIG, _CFGCLKGATEEN, _ENABLE, val);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _CONFIG, _PRBSALT, _PAM4, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIG, val);
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_4);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_4, _MASK_SKIP_OUT, _INIT, val);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_4, _MASK_COM_OUT, _INIT, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_4, val);
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_2);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_2, _SKIP_SYMBOL_0, _SYMBOL, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_2, val);
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_3);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_3, _SKIP_SYMBOL_1, _SYMBOL, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_3, val);
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_0);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_0, _COM_SYMBOL_0, _SYMBOL, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_0, val);
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_1);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_1, _COM_SYMBOL_1, _SYMBOL, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_1, val);
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_4);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_4, _SEND_DATA_OUT, _INIT, val);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_4, _RESET_WORD_CNT_OUT, _COUNT, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _SKIPCOMINSERTERGEN_4, val);
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIGREG);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _CONFIGREG, _TX_BIST_EN_IN, _ENABLE, val);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _CONFIGREG, _DISABLE_WIRED_ENABLE_IN, _ENABLE, val);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _CONFIGREG, _IO_BIST_MODE_IN, _ENABLE, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIGREG, val);
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIG);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _CONFIG, _DPG_PRBSSEEDLD, _ENABLE, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIG, val);
nvswitch_os_sleep(5);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _CONFIG, _DPG_PRBSSEEDLD, _INIT, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIG, val);
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIG);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _CONFIG, _STARTTEST, _ENABLE, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIG, val);
}
else
{
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIG);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _CONFIG, _STARTTEST, _INIT, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIG, val);
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIGREG);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _CONFIGREG, _DISABLE_WIRED_ENABLE_IN, _INIT, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIGREG, val);
val = NVSWITCH_LINK_RD32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIGREG);
val = FLD_SET_DRF(_NVLDL_TXIOBIST, _CONFIGREG, _TX_BIST_EN_IN, _INIT, val);
NVSWITCH_LINK_WR32_LS10(device, linkNumber, NVLDL, _NVLDL_TXIOBIST, _CONFIGREG, val);
}
return NVL_SUCCESS;
}
NvBool
nvswitch_does_link_need_termination_enabled_ls10
(
@@ -1759,3 +1944,116 @@ nvswitch_link_termination_setup_ls10
// Not supported for LS10
return -NVL_ERR_NOT_SUPPORTED;
}
NvlStatus
nvswitch_ctrl_get_link_l1_capability_ls10
(
nvswitch_device *device,
NvU32 linkNum,
NvBool *isL1Capable
)
{
NvU32 regData;
NvBool bL1Capable;
regData = NVSWITCH_LINK_RD32_LS10(device, linkNum, NVLIPT_LNK, _NVLIPT_LNK, _CTRL_SYSTEM_LINK_AN1_CTRL);
bL1Capable = FLD_TEST_DRF(_NVLIPT_LNK, _CTRL_SYSTEM_LINK_AN1_CTRL, _PWRM_L1_ENABLE, _ENABLE, regData);
regData = NVSWITCH_LINK_RD32_LS10(device, linkNum, NVLIPT_LNK, _NVLIPT_LNK, _CTRL_CAP_LOCAL_LINK_AN1);
bL1Capable &= FLD_TEST_DRF(_NVLIPT_LNK, _CTRL_CAP_LOCAL_LINK_AN1, _PWRM_L1_SUPPORT, _SUPPORTED, regData);
*isL1Capable = bL1Capable;
return NVL_SUCCESS;
}
NvlStatus
nvswitch_ctrl_get_link_l1_threshold_ls10
(
nvswitch_device *device,
NvU32 linkNum,
NvU32 *lpThreshold
)
{
NvU32 regData;
regData = NVSWITCH_LINK_RD32_LS10(device, linkNum, NVLIPT_LNK, _NVLIPT_LNK, _PWRM_L1_ENTER_THRESHOLD);
*lpThreshold = DRF_VAL(_NVLIPT, _LNK_PWRM_L1_ENTER_THRESHOLD, _THRESHOLD, regData);
return NVL_SUCCESS;
}
NvlStatus
nvswitch_ctrl_set_link_l1_threshold_ls10
(
nvlink_link *link,
NvU32 lpEntryThreshold
)
{
nvswitch_device *device = link->dev->pDevInfo;
NvU32 linkNum = link->linkNumber;
NvU32 tempRegVal, lpThreshold;
NvU8 softwareDesired;
NvU64 biosVersion;
if (IS_RTLSIM(device) || IS_EMULATION(device) || IS_FMODEL(device))
{
return -NVL_ERR_NOT_SUPPORTED;
}
if (device->regkeys.enable_pm == NV_SWITCH_REGKEY_ENABLE_PM_NO)
{
return -NVL_ERR_NOT_SUPPORTED;
}
if (nvswitch_lib_get_bios_version(device, &biosVersion) != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, WARN, "%s Get VBIOS version failed.\n",
__FUNCTION__);
biosVersion = 0;
}
if (device->regkeys.lp_threshold != NV_SWITCH_REGKEY_SET_LP_THRESHOLD_DEFAULT)
{
lpThreshold = device->regkeys.lp_threshold;
}
else if ((lpEntryThreshold == NVSWITCH_SET_NVLINK_L1_THRESHOLD_DEFAULT) ||
(lpEntryThreshold == NV_SWITCH_REGKEY_SET_LP_THRESHOLD_DEFAULT))
{
if (biosVersion >= BUG_3797211_LS10_VBIOS_VERSION)
{
//
// Read the default L1 Threshold programmed by the
// VBIOS (version 96.10.41.00.00 and above).
//
lpThreshold = NVSWITCH_LINK_RD32_LS10(device, linkNum, NVLIPT_LNK,
_NVLIPT_LNK, _SCRATCH_WARM);
}
else
{
lpThreshold = 1;
}
}
else
{
lpThreshold = lpEntryThreshold;
}
tempRegVal = 0;
tempRegVal = FLD_SET_DRF_NUM(_NVLIPT, _LNK_PWRM_L1_ENTER_THRESHOLD,
_THRESHOLD, lpThreshold, tempRegVal);
NVSWITCH_LINK_WR32_LS10(device, linkNum, NVLIPT_LNK, _NVLIPT_LNK,
_PWRM_L1_ENTER_THRESHOLD, tempRegVal);
//LP Entry Enable
softwareDesired = NV_NVLIPT_LNK_PWRM_CTRL_L1_SOFTWARE_DESIRED_L1;
tempRegVal = NVSWITCH_LINK_RD32_LS10(device, linkNum, NVLIPT_LNK,
_NVLIPT_LNK, _PWRM_CTRL);
tempRegVal = FLD_SET_DRF_NUM(_NVLIPT, _LNK_PWRM_CTRL, _L1_SOFTWARE_DESIRED,
softwareDesired, tempRegVal);
NVSWITCH_LINK_WR32_LS10(device, linkNum, NVLIPT_LNK, _NVLIPT_LNK,
_PWRM_CTRL, tempRegVal);
return NVL_SUCCESS;
}

View File

@@ -37,11 +37,14 @@
#include "ls10/pmgr_ls10.h"
#include "ls10/therm_ls10.h"
#include "ls10/smbpbi_ls10.h"
#include "ls10/cci_ls10.h"
#include "cci/cci_nvswitch.h"
#include "ls10/multicast_ls10.h"
#include "ls10/soe_ls10.h"
#include "ls10/gfw_ls10.h"
#include "nvswitch/ls10/dev_nvs_top.h"
#include "nvswitch/ls10/ptop_discovery_ip.h"
#include "nvswitch/ls10/dev_pri_masterstation_ip.h"
#include "nvswitch/ls10/dev_pri_hub_sys_ip.h"
#include "nvswitch/ls10/dev_nvlw_ip.h"
@@ -1405,10 +1408,12 @@ static NvlStatus
_nvswitch_reset_and_drain_links_ls10
(
nvswitch_device *device,
NvU64 link_mask
NvU64 link_mask,
NvBool bForced
)
{
NvlStatus status = NVL_SUCCESS;
ls10_device *chip_device = NVSWITCH_GET_CHIP_DEVICE_LS10(device);
nvlink_link *link_info = NULL;
NvU32 link;
NvU32 data32;
@@ -1465,6 +1470,11 @@ _nvswitch_reset_and_drain_links_ls10
continue;
}
if (nvswitch_is_link_in_reset(device, link_info))
{
continue;
}
// Unregister links to make them unusable while reset is in progress.
nvlink_lib_unregister_link(link_info);
@@ -1503,46 +1513,54 @@ _nvswitch_reset_and_drain_links_ls10
// Step 3.0 :
// Prior to starting port reset, ensure the links is in emergency shutdown
//
bIsLinkInEmergencyShutdown = NV_FALSE;
nvswitch_timeout_create(10 * NVSWITCH_INTERVAL_1MSEC_IN_NS, &timeout);
do
// Forcibly shutdown links if requested
//
if (bForced)
{
bKeepPolling = (nvswitch_timeout_check(&timeout)) ? NV_FALSE : NV_TRUE;
status = nvswitch_minion_get_dl_status(device, link_info->linkNumber,
NV_NVLSTAT_UC01, 0, &stat_data);
if (status != NVL_SUCCESS)
nvswitch_execute_unilateral_link_shutdown_ls10(link_info);
}
else
{
bIsLinkInEmergencyShutdown = NV_FALSE;
nvswitch_timeout_create(10 * NVSWITCH_INTERVAL_1MSEC_IN_NS, &timeout);
do
{
bKeepPolling = (nvswitch_timeout_check(&timeout)) ? NV_FALSE : NV_TRUE;
status = nvswitch_minion_get_dl_status(device, link_info->linkNumber,
NV_NVLSTAT_UC01, 0, &stat_data);
if (status != NVL_SUCCESS)
{
continue;
}
link_state = DRF_VAL(_NVLSTAT, _UC01, _LINK_STATE, stat_data);
bIsLinkInEmergencyShutdown = (link_state == LINKSTATUS_EMERGENCY_SHUTDOWN) ?
NV_TRUE:NV_FALSE;
if (bIsLinkInEmergencyShutdown == NV_TRUE)
{
break;
}
}
while(bKeepPolling);
if (bIsLinkInEmergencyShutdown == NV_FALSE)
{
NVSWITCH_PRINT(device, ERROR,
"%s: link %d failed to enter emergency shutdown\n",
__FUNCTION__, link);
// Re-register links.
status = nvlink_lib_register_link(device->nvlink_device, link_info);
if (status != NVL_SUCCESS)
{
nvswitch_destroy_link(link_info);
}
continue;
}
link_state = DRF_VAL(_NVLSTAT, _UC01, _LINK_STATE, stat_data);
bIsLinkInEmergencyShutdown = (link_state == LINKSTATUS_EMERGENCY_SHUTDOWN) ?
NV_TRUE:NV_FALSE;
if (bIsLinkInEmergencyShutdown == NV_TRUE)
{
break;
}
}
while(bKeepPolling);
if (bIsLinkInEmergencyShutdown == NV_FALSE)
{
NVSWITCH_PRINT(device, ERROR,
"%s: link %d failed to enter emergency shutdown\n",
__FUNCTION__, link);
// Re-register links.
status = nvlink_lib_register_link(device->nvlink_device, link_info);
if (status != NVL_SUCCESS)
{
nvswitch_destroy_link(link_info);
}
continue;
}
nvswitch_corelib_clear_link_state_ls10(link_info);
@@ -1585,30 +1603,25 @@ _nvswitch_reset_and_drain_links_ls10
NV_NVLSTAT_MN00, 0, &stat_data) == NVL_SUCCESS)
{
link_intr_subcode = DRF_VAL(_NVLSTAT, _MN00, _LINK_INTR_SUBCODE, stat_data);
}
else
{
continue;
}
if ((link_state == NV_NVLIPT_LNK_CTRL_LINK_STATE_REQUEST_STATUS_MINION_REQUEST_FAIL) &&
(link_intr_subcode == MINION_ALARM_BUSY))
{
if ((link_state == NV_NVLIPT_LNK_CTRL_LINK_STATE_REQUEST_STATUS_MINION_REQUEST_FAIL) &&
(link_intr_subcode == MINION_ALARM_BUSY))
{
status = nvswitch_request_tl_link_state_ls10(link_info,
NV_NVLIPT_LNK_CTRL_LINK_STATE_REQUEST_REQUEST_RESET, NV_TRUE);
//
// We retry the shutdown sequence 3 times when we see a MINION_REQUEST_FAIL
// or MINION_ALARM_BUSY
//
retry_count--;
}
else
{
break;
//
// We retry the reset sequence when we see a MINION_REQUEST_FAIL
// or MINION_ALARM_BUSY
//
}
else
{
break;
}
}
retry_count--;
}
} while(retry_count);
if (status != NVL_SUCCESS)
@@ -1651,6 +1664,9 @@ _nvswitch_reset_and_drain_links_ls10
continue;
}
// Initialize select scratch registers to 0x0
device->hal.nvswitch_init_scratch(device);
//
// Step 9.0: Launch ALI training to re-initialize and train the links
// nvswitch_launch_ALI_link_training(device, link_info);
@@ -1658,6 +1674,8 @@ _nvswitch_reset_and_drain_links_ls10
// Request active, but don't block. FM will come back and check
// active link status by blocking on this TLREQ's completion
//
// CCI will re-train links
if (!cciIsLinkManaged(device, link))
{
status = nvswitch_request_tl_link_state_ls10(link_info,
NV_NVLIPT_LNK_CTRL_LINK_STATE_REQUEST_REQUEST_ACTIVE,
@@ -1698,6 +1716,8 @@ _nvswitch_reset_and_drain_links_ls10
}
FOR_EACH_INDEX_IN_MASK_END;
chip_device->deferredLinkErrors[link].state.lastRetrainTime = nvswitch_os_get_platform_time();
return NVL_SUCCESS;
}
@@ -1708,12 +1728,25 @@ NvlStatus
nvswitch_reset_and_drain_links_ls10
(
nvswitch_device *device,
NvU64 link_mask
NvU64 link_mask,
NvBool bForced
)
{
NvlStatus status = NVL_SUCCESS;
status = _nvswitch_reset_and_drain_links_ls10(device, link_mask);
NvU32 link;
// CCI will call reset and drain separately
FOR_EACH_INDEX_IN_MASK(64, link, link_mask)
{
if (cciIsLinkManaged(device, link))
{
link_mask = link_mask & ~NVBIT64(link);
}
}
FOR_EACH_INDEX_IN_MASK_END;
status = _nvswitch_reset_and_drain_links_ls10(device, link_mask, bForced);
if (status != NVL_SUCCESS)
{
return status;
@@ -5163,6 +5196,10 @@ nvswitch_launch_ALI_ls10
continue;
}
if (cciIsLinkManaged(device, i))
{
continue;
}
nvswitch_launch_ALI_link_training(device, link, NV_FALSE);
}
FOR_EACH_INDEX_IN_MASK_END;
@@ -5512,7 +5549,7 @@ nvswitch_ctrl_inband_send_data_ls10
NvlStatus status;
nvswitch_inband_send_data inBandData;
// ct_assert(NVLINK_INBAND_MAX_MSG_SIZE >= NVSWITCH_INBAND_DATA_SIZE);
ct_assert(NVLINK_INBAND_MAX_MSG_SIZE == NVSWITCH_INBAND_DATA_SIZE);
if (p->dataSize == 0 || p->dataSize > NVSWITCH_INBAND_DATA_SIZE)
{
@@ -5858,6 +5895,514 @@ nvswitch_ctrl_get_nvlink_error_threshold_ls10
return NVL_SUCCESS;
}
NvlStatus
nvswitch_get_board_id_ls10
(
nvswitch_device *device,
NvU16 *pBoardId
)
{
NvlStatus ret;
NvU32 biosOemVersionBytes;
if (pBoardId == NULL)
{
return -NVL_BAD_ARGS;
}
// Check if bios valid
ret = nvswitch_lib_get_bios_version(device, NULL);
if (ret != NVL_SUCCESS)
{
return ret;
}
biosOemVersionBytes = NVSWITCH_SAW_RD32_LS10(device, _NVLSAW_SW,
_OEM_BIOS_VERSION);
*pBoardId = DRF_VAL(_NVLSAW_SW, _OEM_BIOS_VERSION, _BOARD_ID, biosOemVersionBytes);
return NVL_SUCCESS;
}
NvlStatus
nvswitch_check_io_sanity_ls10
(
nvswitch_device *device
)
{
NvBool keepPolling;
NVSWITCH_TIMEOUT timeout;
NvU32 val;
NvBool error = NV_FALSE;
NvU32 sxid;
const char *sxid_desc = NULL;
//
// NOTE: MMIO discovery has not been performed so only constant BAR0 offset
// addressing can be performed.
//
// BAR0 offset 0 should always contain valid data -- unless it doesn't
val = NVSWITCH_OFF_RD32(device, 0);
if (val == 0)
{
error = NV_TRUE;
sxid = NVSWITCH_ERR_HW_HOST_FIRMWARE_RECOVERY_MODE;
sxid_desc = "Firmware recovery mode";
}
else if ((val == 0xFFFFFFFF) || ((val & 0xFFFF0000) == 0xBADF0000))
{
error = NV_TRUE;
sxid = NVSWITCH_ERR_HW_HOST_IO_FAILURE;
sxid_desc = "IO failure";
}
else if (!IS_FMODEL(device))
{
// check if FSP successfully started
nvswitch_timeout_create(10 * NVSWITCH_INTERVAL_1SEC_IN_NS, &timeout);
do
{
keepPolling = (nvswitch_timeout_check(&timeout)) ? NV_FALSE : NV_TRUE;
val = NVSWITCH_REG_RD32(device, _GFW_GLOBAL, _BOOT_PARTITION_PROGRESS);
if (FLD_TEST_DRF(_GFW_GLOBAL, _BOOT_PARTITION_PROGRESS, _VALUE, _SUCCESS, val))
{
break;
}
nvswitch_os_sleep(1);
}
while (keepPolling);
if (!FLD_TEST_DRF(_GFW_GLOBAL, _BOOT_PARTITION_PROGRESS, _VALUE, _SUCCESS, val))
{
error = NV_TRUE;
sxid = NVSWITCH_ERR_HW_HOST_FIRMWARE_INITIALIZATION_FAILURE;
sxid_desc = "Firmware initialization failure";
}
}
if (error)
{
NVSWITCH_RAW_ERROR_LOG_TYPE report = { 0, { 0 } };
NVSWITCH_RAW_ERROR_LOG_TYPE report_saw = {0, { 0 }};
NvU32 report_idx = 0;
NvU32 i;
val = NVSWITCH_REG_RD32(device, _GFW_GLOBAL, _BOOT_PARTITION_PROGRESS);
report.data[report_idx++] = val;
NVSWITCH_PRINT(device, ERROR, "%s: -- _GFW_GLOBAL, _BOOT_PARTITION_PROGRESS (0x%x) != _SUCCESS --\n",
__FUNCTION__, val);
for (i = 0; i <= 15; i++)
{
val = NVSWITCH_OFF_RD32(device,
NV_PTOP_UNICAST_SW_DEVICE_BASE_SAW_0 + NV_NVLSAW_SW_SCRATCH(i));
report_saw.data[i] = val;
NVSWITCH_PRINT(device, ERROR, "%s: -- NV_NVLSAW_SW_SCRATCH(%d) = 0x%08x\n",
__FUNCTION__, i, val);
}
for (i = 0; i < NV_PFSP_FALCON_COMMON_SCRATCH_GROUP_2__SIZE_1; i++)
{
val = NVSWITCH_REG_RD32(device, _PFSP, _FALCON_COMMON_SCRATCH_GROUP_2(i));
report.data[report_idx++] = val;
NVSWITCH_PRINT(device, ERROR, "%s: -- NV_PFSP_FALCON_COMMON_SCRATCH_GROUP_2(%d) = 0x%08x\n",
__FUNCTION__, i, val);
}
// Include useful scratch information for triage
NVSWITCH_PRINT_SXID_NO_BBX(device, sxid,
"Fatal, %s (0x%x/0x%x, 0x%x, 0x%x, 0x%x/0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", sxid_desc,
report.data[0], report.data[1], report.data[2], report.data[3], report.data[4],
report_saw.data[0], report_saw.data[1], report_saw.data[12], report_saw.data[14], report_saw.data[15]);
return -NVL_INITIALIZATION_TOTAL_FAILURE;
}
return NVL_SUCCESS;
}
/*
* @brief: This function returns the current value of the SOE heartbeat gpio
* @params[in] device reference to current nvswitch device
* @params[in] p NVSWITCH_GET_SOE_HEARTBEAT_PARAMS
*/
NvlStatus
nvswitch_ctrl_get_soe_heartbeat_ls10
(
nvswitch_device *device,
NVSWITCH_GET_SOE_HEARTBEAT_PARAMS *p
)
{
NvU32 gpioVal = 0;
NvU64 hi = 0;
NvU64 lo = 0;
NvU64 test = 0;
if (!nvswitch_is_cci_supported(device))
{
return -NVL_ERR_NOT_SUPPORTED;
}
// Read status of heartbeat gpio
gpioVal = NVSWITCH_REG_RD32(device, _GPIO, _OUTPUT_CNTL(3));
// Record timestamp of gpio read from PTIMER
do
{
hi = NVSWITCH_ENG_RD32(device, PTIMER, , 0, _PTIMER, _TIME_1);
lo = NVSWITCH_ENG_RD32(device, PTIMER, , 0, _PTIMER, _TIME_0);
test = NVSWITCH_ENG_RD32(device, PTIMER, , 0, _PTIMER, _TIME_1);
}
while (hi != test);
p->timestampNs = (hi << 32) | lo;
if (FLD_TEST_DRF(_GPIO, _OUTPUT_CNTL, _IO_OUTPUT, _1, gpioVal))
{
p->gpioVal = 1;
}
else if (FLD_TEST_DRF(_GPIO, _OUTPUT_CNTL, _IO_OUTPUT, _0, gpioVal))
{
p->gpioVal = 0;
}
return NVL_SUCCESS;
}
static NvlStatus
nvswitch_cci_reset_and_drain_links_ls10
(
nvswitch_device *device,
NvU64 link_mask,
NvBool bForced
)
{
NvU32 link;
FOR_EACH_INDEX_IN_MASK(64, link, link_mask)
{
if (!cciIsLinkManaged(device, link))
{
link_mask = link_mask & ~NVBIT64(link);
}
}
FOR_EACH_INDEX_IN_MASK_END;
return _nvswitch_reset_and_drain_links_ls10(device, link_mask, bForced);
}
/*
* @brief Set the next LED state
* The HW will reflect this state on the next iteration of link
* state update.
*/
static void
_nvswitch_set_next_led_state_ls10
(
nvswitch_device *device,
NvU8 nextLedState
)
{
device->next_led_state = nextLedState;
}
/*
* Returns the CPLD register value assigned to a particular LED state
* confluence page ID: 1011518154
*/
static NvU8
_nvswitch_get_led_state_regval_ls10
(
nvswitch_device *device,
NvU8 ledState
)
{
switch (ledState)
{
case ACCESS_LINK_LED_STATE_OFF:
{
return CPLD_MACHXO3_ACCESS_LINK_LED_CTL_NVL_CABLE_LED_REG_STATE_OFF;
}
case ACCESS_LINK_LED_STATE_UP_WARM:
{
return CPLD_MACHXO3_ACCESS_LINK_LED_CTL_NVL_CABLE_LED_REG_STATE_GREEN;
}
case ACCESS_LINK_LED_STATE_INITIALIZE:
{
return CPLD_MACHXO3_ACCESS_LINK_LED_CTL_NVL_CABLE_LED_REG_STATE_3HZ_AMBER;
}
case ACCESS_LINK_LED_STATE_UP_ACTIVE:
{
return CPLD_MACHXO3_ACCESS_LINK_LED_CTL_NVL_CABLE_LED_REG_STATE_3HZ_GREEN;
}
case ACCESS_LINK_LED_STATE_FAULT:
{
return CPLD_MACHXO3_ACCESS_LINK_LED_CTL_NVL_CABLE_LED_REG_STATE_6HZ_AMBER;
}
default:
{
NVSWITCH_ASSERT(0);
return CPLD_MACHXO3_ACCESS_LINK_LED_CTL_NVL_CABLE_LED_REG_STATE_OFF;
}
}
}
/*
* @brief Set HW LED state using CPLD write
*
*/
static NvlStatus
_nvswitch_set_led_state_ls10
(
nvswitch_device *device
)
{
NvlStatus retval;
NvU8 ledState;
NvU8 nextLedState;
NvU8 regVal = 0;
nextLedState = device->next_led_state;
ledState = REF_VAL(ACCESS_LINK_LED_STATE, nextLedState);
regVal = FLD_SET_REF_NUM(CPLD_MACHXO3_ACCESS_LINK_LED_CTL_NVL_CABLE_LED,
_nvswitch_get_led_state_regval_ls10(device, ledState),
regVal);
// Set state for LED
retval = nvswitch_cci_ports_cpld_write(device, CPLD_MACHXO3_ACCESS_LINK_LED_CTL, regVal);
if (retval != NVL_SUCCESS)
{
return retval;
}
// save HW state
device->current_led_state = REF_NUM(ACCESS_LINK_LED_STATE, ledState);
return NVL_SUCCESS;
}
static NvBool
_nvswitch_check_for_link_traffic
(
nvswitch_device *device,
NvU64 linkMask
)
{
NVSWITCH_GET_THROUGHPUT_COUNTERS_PARAMS *pCounterParams = NULL;
NvU64 *pCounterValues;
NvU64 tpCounterPreviousSum;
NvU64 tpCounterCurrentSum;
NvBool bTraffic = NV_FALSE;
NvU8 linkNum;
pCounterParams = nvswitch_os_malloc(sizeof(*pCounterParams));
if (pCounterParams == NULL)
goto out;
pCounterParams->counterMask = NVSWITCH_THROUGHPUT_COUNTERS_TYPE_DATA_TX |
NVSWITCH_THROUGHPUT_COUNTERS_TYPE_DATA_RX;
pCounterParams->linkMask = linkMask;
if (nvswitch_ctrl_get_throughput_counters(device,
pCounterParams) != NVL_SUCCESS)
{
goto out;
}
// Sum TX/RX traffic for each link
FOR_EACH_INDEX_IN_MASK(64, linkNum, linkMask)
{
pCounterValues = pCounterParams->counters[linkNum].values;
tpCounterPreviousSum = device->tp_counter_previous_sum[linkNum];
// Sum taken to save space as it is unlikely to overflow before system is reset
tpCounterCurrentSum = pCounterValues[NVSWITCH_THROUGHPUT_COUNTERS_TYPE_DATA_TX] +
pCounterValues[NVSWITCH_THROUGHPUT_COUNTERS_TYPE_DATA_RX];
device->tp_counter_previous_sum[linkNum] = tpCounterCurrentSum;
if (tpCounterCurrentSum > tpCounterPreviousSum)
{
bTraffic = NV_TRUE;
}
}
FOR_EACH_INDEX_IN_MASK_END;
out:
nvswitch_os_free(pCounterParams);
return bTraffic;
}
static NvU8
_nvswitch_resolve_led_state_ls10
(
nvswitch_device *device,
NvU8 ledState0,
NvU8 ledState1
)
{
// Used to resolve link state discrepancies between partner links
ct_assert(ACCESS_LINK_LED_STATE_FAULT < ACCESS_LINK_LED_STATE_OFF);
ct_assert(ACCESS_LINK_LED_STATE_OFF < ACCESS_LINK_LED_STATE_INITIALIZE);
ct_assert(ACCESS_LINK_LED_STATE_INITIALIZE < ACCESS_LINK_LED_STATE_UP_WARM);
return (ledState0 < ledState1 ? ledState0 : ledState1);
}
static NvU8
_nvswitch_get_next_led_state_link_ls10
(
nvswitch_device *device,
NvU8 currentLedState,
NvU8 linkNum
)
{
nvlink_link *link;
NvU64 linkState;
link = nvswitch_get_link(device, linkNum);
if ((link == NULL) ||
(device->hal.nvswitch_corelib_get_dl_link_mode(link, &linkState) != NVL_SUCCESS))
{
return ACCESS_LINK_LED_STATE_OFF;
}
switch (linkState)
{
case NVLINK_LINKSTATE_OFF:
{
return ACCESS_LINK_LED_STATE_OFF;
}
case NVLINK_LINKSTATE_HS:
case NVLINK_LINKSTATE_RECOVERY:
case NVLINK_LINKSTATE_SLEEP:
{
return ACCESS_LINK_LED_STATE_UP_WARM;
}
case NVLINK_LINKSTATE_FAULT:
{
return ACCESS_LINK_LED_STATE_FAULT;
}
default:
{
if (currentLedState == ACCESS_LINK_LED_STATE_INITIALIZE)
{
return ACCESS_LINK_LED_STATE_INITIALIZE;
}
return ACCESS_LINK_LED_STATE_OFF;
}
}
}
static NvU8
_nvswitch_get_next_led_state_links_ls10
(
nvswitch_device *device,
NvU8 currentLedState,
NvU64 linkMask
)
{
NvU8 linkNum;
NvU8 ledState;
NvU8 nextLedState;
nextLedState = ACCESS_LINK_NUM_LED_STATES;
NVSWITCH_ASSERT(linkMask != 0);
FOR_EACH_INDEX_IN_MASK(64, linkNum, linkMask)
{
ledState = _nvswitch_get_next_led_state_link_ls10(device, currentLedState, linkNum);
nextLedState = _nvswitch_resolve_led_state_ls10(device, nextLedState, ledState);
}
FOR_EACH_INDEX_IN_MASK_END;
if (nextLedState == ACCESS_LINK_LED_STATE_UP_WARM)
{
// Only tells us that one of the links has activity
if (_nvswitch_check_for_link_traffic(device, linkMask))
{
nextLedState = ACCESS_LINK_LED_STATE_UP_ACTIVE;
}
}
return nextLedState;
}
static NvU8
_nvswitch_get_next_led_state_ls10
(
nvswitch_device *device
)
{
NvU8 linkNum;
NvU8 ledNextState = 0;
NvU8 currentLedState;
NvU64 enabledLinkMask;
enabledLinkMask = nvswitch_get_enabled_link_mask(device);
FOR_EACH_INDEX_IN_MASK(64, linkNum, enabledLinkMask)
{
if (cciIsLinkManaged(device, linkNum))
{
enabledLinkMask = enabledLinkMask & ~NVBIT64(linkNum);
}
}
FOR_EACH_INDEX_IN_MASK_END;
currentLedState = device->current_led_state;
currentLedState = REF_VAL(ACCESS_LINK_LED_STATE, currentLedState);
ledNextState = FLD_SET_REF_NUM(ACCESS_LINK_LED_STATE,
_nvswitch_get_next_led_state_links_ls10(device,
currentLedState,
enabledLinkMask),
ledNextState);
return ledNextState;
}
void
nvswitch_update_link_state_led_ls10
(
nvswitch_device *device
)
{
NvU8 currentLedState;
NvU8 nextLedState;
currentLedState = device->current_led_state;
currentLedState = REF_VAL(ACCESS_LINK_LED_STATE, currentLedState);
nextLedState = _nvswitch_get_next_led_state_ls10(device);
// This is the next state that the LED will be set to
_nvswitch_set_next_led_state_ls10(device, nextLedState);
// Only update HW if required
if (currentLedState != nextLedState)
{
_nvswitch_set_led_state_ls10(device);
}
}
void
nvswitch_led_shutdown_ls10
(
nvswitch_device *device
)
{
NvU8 ledState = 0;
ledState = FLD_SET_REF_NUM(ACCESS_LINK_LED_STATE,
ACCESS_LINK_LED_STATE_OFF, ledState);
// This is the next state that the LED will be set to
_nvswitch_set_next_led_state_ls10(device, ledState);
_nvswitch_set_led_state_ls10(device);
}
NvlStatus
nvswitch_read_vbios_link_entries_ls10
(
@@ -6009,6 +6554,27 @@ nvswitch_ctrl_get_inforom_version_ls10
return NVL_SUCCESS;
}
/*
* @Brief : Initializes an NvSwitch hardware state
*
* @Description :
*
* @param[in] device a reference to the device to initialize
*
* @returns NVL_SUCCESS if the action succeeded
* -NVL_BAD_ARGS if bad arguments provided
* -NVL_PCI_ERROR if bar info unable to be retrieved
*/
NvlStatus
nvswitch_initialize_device_state_ls10
(
nvswitch_device *device
)
{
device->bModeContinuousALI = NV_TRUE;
return nvswitch_initialize_device_state_lr10(device);
}
//
// This function auto creates the ls10 HAL connectivity from the NVSWITCH_INIT_HAL
// macro in haldef_nvswitch.h

View File

@@ -512,10 +512,9 @@ nvswitch_soe_disable_nport_fatal_interrupts_ls10
NVSWITCH_TIMEOUT timeout;
RM_SOE_CORE_CMD_NPORT_FATAL_INTR *pNportIntrDisable;
NVSWITCH_GET_BIOS_INFO_PARAMS p = { 0 };
NvlStatus stat;
stat = device->hal.nvswitch_ctrl_get_bios_info(device, &p);
if ((stat != NVL_SUCCESS) || ((p.version & SOE_VBIOS_VERSION_MASK) <
status = device->hal.nvswitch_ctrl_get_bios_info(device, &p);
if ((status != NVL_SUCCESS) || ((p.version & SOE_VBIOS_VERSION_MASK) <
SOE_VBIOS_REVLOCK_DISABLE_NPORT_FATAL_INTR))
{
NVSWITCH_PRINT(device, ERROR,
@@ -696,6 +695,40 @@ nvswitch_soe_register_event_callbacks_ls10
return -NVL_ERR_INVALID_STATE;
}
// Register CCI callback funcion
status = flcnQueueEventRegister(
device, pFlcn,
RM_SOE_UNIT_CCI,
NULL,
nvswitch_cci_soe_callback_ls10,
NULL,
&pSoe->cciEvtDesc);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to register CCI event handler.\n",
__FUNCTION__);
return -NVL_ERR_INVALID_STATE;
}
// Register Heartbeat callback funcion
status = flcnQueueEventRegister(
device, pFlcn,
RM_SOE_UNIT_HEARTBEAT,
NULL,
nvswitch_heartbeat_soe_callback_ls10,
NULL,
&pSoe->heartbeatEvtDesc);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to register Heartbeat event handler.\n",
__FUNCTION__);
return -NVL_ERR_INVALID_STATE;
}
return NVL_SUCCESS;
}
@@ -718,6 +751,25 @@ nvswitch_soe_unregister_events_ls10
"%s: Failed to un-register thermal event handler.\n",
__FUNCTION__);
}
// un-register thermal callback funcion
status = flcnQueueEventUnregister(device, pFlcn,
pSoe->cciEvtDesc);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to un-register cci event handler.\n",
__FUNCTION__);
}
// un-register heartbeat callback funcion
status = flcnQueueEventUnregister(device, pFlcn,
pSoe->heartbeatEvtDesc);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to un-register heartbeat event handler.\n",
__FUNCTION__);
}
}
/*!