520.61.05

This commit is contained in:
Andy Ritger
2022-10-10 14:59:24 -07:00
parent fe0728787f
commit 90eb10774f
758 changed files with 88383 additions and 26493 deletions

View File

@@ -343,3 +343,35 @@ soeSetPcieLinkSpeed_HAL
return pSoe->base.pHal->setPcieLinkSpeed(device, linkSpeed);
}
NV_STATUS
soeProcessMessages_HAL
(
nvswitch_device *device,
PSOE pSoe
)
{
if (pSoe->base.pHal->processMessages == NULL)
{
NVSWITCH_ASSERT(0);
return 0;
}
return pSoe->base.pHal->processMessages(device, pSoe);
}
NV_STATUS
soeWaitForInitAck_HAL
(
nvswitch_device *device,
PSOE pSoe
)
{
if (pSoe->base.pHal->waitForInitAck == NULL)
{
NVSWITCH_ASSERT(0);
return 0;
}
return pSoe->base.pHal->waitForInitAck(device, pSoe);
}

View File

@@ -31,365 +31,6 @@
#include "rmflcncmdif_nvswitch.h"
#include "common_nvswitch.h"
static NV_STATUS _soeGetInitMessage(nvswitch_device *device, PSOE pSoe, RM_FLCN_MSG_SOE *pMsg);
/*!
* Use the SOE INIT Message to construct and initialize all SOE Queues.
*
* @param[in] device nvswitch_device pointer
* @param[in] pSoe SOE object pointer
* @param[in] pMsg Pointer to the INIT Message
*
* @return 'NV_OK' upon successful creation of all SOE Queues
*/
static NV_STATUS
_soeQMgrCreateQueuesFromInitMsg
(
nvswitch_device *device,
PFLCNABLE pSoe,
RM_FLCN_MSG_SOE *pMsg
)
{
RM_SOE_INIT_MSG_SOE_INIT *pInit;
NvU32 i;
NvU32 queueLogId;
NV_STATUS status;
FLCNQUEUE *pQueue;
PFLCN pFlcn = ENG_GET_FLCN(pSoe);
PFALCON_QUEUE_INFO pQueueInfo;
NVSWITCH_ASSERT(pFlcn != NULL);
pQueueInfo = pFlcn->pQueueInfo;
NVSWITCH_ASSERT(pQueueInfo != NULL);
pInit = &pMsg->msg.init.soeInit;
NVSWITCH_ASSERT(pInit->numQueues <= pFlcn->numQueues);
for (i = 0; i < pFlcn->numQueues; i++)
{
queueLogId = pInit->qInfo[i].queueLogId;
NVSWITCH_ASSERT(queueLogId < pFlcn->numQueues);
pQueue = &pQueueInfo->pQueues[queueLogId];
status = flcnQueueConstruct_dmem_nvswitch(
device,
pFlcn,
&pQueue, // ppQueue
queueLogId, // Logical ID of the queue
pInit->qInfo[i].queuePhyId, // Physical ID of the queue
pInit->qInfo[i].queueOffset, // offset
pInit->qInfo[i].queueSize, // size
RM_FLCN_QUEUE_HDR_SIZE); // cmdHdrSize
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Error constructing SOE Queue (status="
"0x%08x).\n", __FUNCTION__, status);
NVSWITCH_ASSERT(0);
return status;
}
}
return NV_OK;
}
/*!
* Purges all the messages from the SOE's message queue. Each message will
* be analyzed, clients will be notified of status, and events will be routed
* to all registered event listeners.
*
* @param[in] device nvswitch_device pointer
* @param[in] pSoe SOE object pointer
*
* @return 'NV_OK' if the message queue was successfully purged.
*/
static NV_STATUS
_soeProcessMessages_IMPL
(
nvswitch_device *device,
PSOE pSoe
)
{
RM_FLCN_MSG_SOE soeMessage;
NV_STATUS status;
PFLCN pFlcn = ENG_GET_FLCN(pSoe);
// keep processing messages until no more exist in the message queue
while (NV_OK == (status = flcnQueueReadData(
device,
pFlcn,
SOE_RM_MSGQ_LOG_ID,
(RM_FLCN_MSG *)&soeMessage, NV_TRUE)))
{
NVSWITCH_PRINT(device, INFO,
"%s: unitId=0x%02x, size=0x%02x, ctrlFlags=0x%02x, " \
"seqNumId=0x%02x\n",
__FUNCTION__,
soeMessage.hdr.unitId,
soeMessage.hdr.size,
soeMessage.hdr.ctrlFlags,
soeMessage.hdr.seqNumId);
// check to see if the message is a reply or an event.
if ((soeMessage.hdr.ctrlFlags &= RM_FLCN_QUEUE_HDR_FLAGS_EVENT) != 0)
{
flcnQueueEventHandle(device, pFlcn, (RM_FLCN_MSG *)&soeMessage, NV_OK);
}
// the message is a response from a previously queued command
else
{
flcnQueueResponseHandle(device, pFlcn, (RM_FLCN_MSG *)&soeMessage);
}
}
//
// Status NV_ERR_NOT_READY implies, Queue is empty.
// Log the message in other error cases.
//
if (status != NV_ERR_NOT_READY)
{
NVSWITCH_PRINT(device, ERROR,
"%s: unexpected error while purging message queue (status=0x%x).\n",
__FUNCTION__, (status));
}
return status;
}
/*!
* This function exists to solve a natural chicken-and-egg problem that arises
* due to the fact that queue information (location, size, id, etc...) is
* relayed to the RM as a message in a queue. Queue construction is done when
* the message arives and the normal queue read/write functions are not
* available until construction is complete. Construction cannot be done until
* the message is read from the queue. Therefore, the very first message read
* from the Message Queue must be considered as a special-case and must NOT use
* any functionality provided by the SOE's queue manager.
*
* @param[in] device nvswitch_device pointer
* @param[in] pSoe SOE object pointer
*
* @return 'NV_OK'
* Upon successful extraction and processing of the first SOE message.
*/
static NV_STATUS
_soeProcessMessagesPreInit_IMPL
(
nvswitch_device *device,
PSOE pSoe
)
{
RM_FLCN_MSG_SOE msg;
NV_STATUS status;
PFLCN pFlcn = ENG_GET_FLCN(pSoe);
// extract the "INIT" message (this is never expected to fail)
status = _soeGetInitMessage(device, pSoe, &msg);
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to extract the INIT message "
"from the SOE Message Queue (status=0x%08x).",
__FUNCTION__, status);
NVSWITCH_ASSERT(0);
return status;
}
//
// Now hookup the "real" message-processing function and handle the "INIT"
// message.
//
pSoe->base.pHal->processMessages = _soeProcessMessages_IMPL;
return flcnQueueEventHandle(device, pFlcn, (RM_FLCN_MSG *)&msg, NV_OK);
}
/*!
* @brief Process the "INIT" message sent from the SOE ucode application.
*
* When the SOE ucode is done initializing, it will post an INIT message in
* the Message Queue that contains all the necessary attributes that are
* needed to enqueuing commands and extracting messages from the queues.
* The packet will also contain the offset and size of portion of DMEM that
* the RM must manage. Upon receiving this message it will be assume that
* the SOE is ready to start accepting commands.
*
* @param[in] device nvswitch_device pointer
* @param[in] pSoe SOE object pointer
* @param[in] pMsg Pointer to the event's message data
*
* @return 'NV_OK' if the event was successfully handled.
*/
static NV_STATUS
_soeHandleInitEvent_IMPL
(
nvswitch_device *device,
PFLCNABLE pSoe,
RM_FLCN_MSG *pGenMsg
)
{
NV_STATUS status;
PFLCN pFlcn = ENG_GET_FLCN(pSoe);
RM_FLCN_MSG_SOE *pMsg = (RM_FLCN_MSG_SOE *)pGenMsg;
if (pFlcn == NULL)
{
NVSWITCH_ASSERT(pFlcn != NULL);
return NV_ERR_INVALID_POINTER;
}
NVSWITCH_PRINT(device, INFO,
"%s: Received INIT message from SOE\n",
__FUNCTION__);
//
// Pass the INIT message to the queue manager to allow it to create the
// queues.
//
status = _soeQMgrCreateQueuesFromInitMsg(device, pSoe, pMsg);
if (status != NV_OK)
{
NVSWITCH_ASSERT(0);
return status;
}
flcnDbgInfoDmemOffsetSet(device, pFlcn,
pMsg->msg.init.soeInit.osDebugEntryPoint);
// the SOE ucode is now initialized and ready to accept commands
pFlcn->bOSReady = NV_TRUE;
return NV_OK;
}
/*!
* @brief Read the INIT message directly out of the Message Queue.
*
* This function accesses the Message Queue directly using the HAL. It does
* NOT and may NOT use the queue manager as it has not yet been constructed and
* initialized. The Message Queue may not be empty when this function is called
* and the first message in the queue MUST be the INIT message.
*
* @param[in] device nvswitch_device pointer
* @param[in] pSoe SOE object pointer
* @param[out] pMsg Message structure to fill with the INIT message data
*
* @return 'NV_OK' upon successful extraction of the INIT message.
* @return
* 'NV_ERR_INVALID_STATE' if the first message found was not an INIT
* message or if the message was improperly formatted.
*/
static NV_STATUS
_soeGetInitMessage
(
nvswitch_device *device,
PSOE pSoe,
RM_FLCN_MSG_SOE *pMsg
)
{
PFLCN pFlcn = ENG_GET_FLCN(pSoe);
NV_STATUS status = NV_OK;
NvU32 tail = 0;
PFALCON_QUEUE_INFO pQueueInfo;
// on the GPU, rmEmemPortId = sec2RmEmemPortIdGet_HAL(...);
NvU8 rmEmemPortId = 0;
if (pFlcn == NULL)
{
NVSWITCH_ASSERT(pFlcn != NULL);
return NV_ERR_INVALID_POINTER;
}
pQueueInfo = pFlcn->pQueueInfo;
if (pQueueInfo == NULL)
{
NVSWITCH_ASSERT(pQueueInfo != NULL);
return NV_ERR_INVALID_POINTER;
}
//
// Message queue 0 is used by SOE to communicate with RM
// Check SOE_CMDMGMT_MSG_QUEUE_RM in //uproc/soe/inc/soe_cmdmgmt.h
//
pQueueInfo->pQueues[SOE_RM_MSGQ_LOG_ID].queuePhyId = 0;
// read the header starting at the current tail position
(void)flcnMsgQueueTailGet(device, pFlcn,
&pQueueInfo->pQueues[SOE_RM_MSGQ_LOG_ID], &tail);
if (pFlcn->bEmemEnabled)
{
//
// We use the offset in DMEM for the src address, since
// EmemCopyFrom automatically converts it to the offset in EMEM
//
flcnableEmemCopyFrom(
device, pFlcn->pFlcnable,
tail, // src
(NvU8 *)&pMsg->hdr, // pDst
RM_FLCN_QUEUE_HDR_SIZE, // numBytes
rmEmemPortId); // port
}
else
{
status = flcnDmemCopyFrom(device,
pFlcn,
tail, // src
(NvU8 *)&pMsg->hdr, // pDst
RM_FLCN_QUEUE_HDR_SIZE, // numBytes
0); // port
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to copy from SOE DMEM\n", __FUNCTION__);
NVSWITCH_ASSERT(0);
goto _soeGetInitMessage_exit;
}
}
if (pMsg->hdr.unitId != RM_SOE_UNIT_INIT)
{
status = NV_ERR_INVALID_STATE;
NVSWITCH_ASSERT(0);
goto _soeGetInitMessage_exit;
}
// read the message body and update the tail position
if (pFlcn->bEmemEnabled)
{
//
// We use the offset in DMEM for the src address, since
// EmemCopyFrom automatically converts it to the offset in EMEM
//
flcnableEmemCopyFrom(
device, pFlcn->pFlcnable,
tail + RM_FLCN_QUEUE_HDR_SIZE, // src
(NvU8 *)&pMsg->msg, // pDst
pMsg->hdr.size - RM_FLCN_QUEUE_HDR_SIZE, // numBytes
rmEmemPortId); // port
}
else
{
status = flcnDmemCopyFrom(device,
pFlcn,
tail + RM_FLCN_QUEUE_HDR_SIZE, // src
(NvU8 *)&pMsg->msg, // pDst
pMsg->hdr.size - RM_FLCN_QUEUE_HDR_SIZE, // numBytes
0); // port
if (status != NV_OK)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to copy from SOE DMEM\n", __FUNCTION__);
NVSWITCH_ASSERT(0);
goto _soeGetInitMessage_exit;
}
}
tail += NV_ALIGN_UP(pMsg->hdr.size, SOE_DMEM_ALIGNMENT);
flcnMsgQueueTailSet(device, pFlcn,
&pQueueInfo->pQueues[SOE_RM_MSGQ_LOG_ID], tail);
_soeGetInitMessage_exit:
return status;
}
/*!
* Copies 'sizeBytes' from DMEM address 'src' to 'pDst' using EMEM access port.
*
@@ -444,43 +85,6 @@ _soeEmemCopyTo_IMPL
soeEmemTransfer_HAL(device, (PSOE)pSoe, dst, pSrc, sizeBytes, port, NV_FALSE);
}
/*!
* Loop until SOE RTOS is loaded and gives us an INIT message
*
* @param[in] device nvswitch_device object pointer
* @param[in] pSoe SOE object pointer
*/
static NV_STATUS
_soeWaitForInitAck_IMPL
(
nvswitch_device *device,
PSOE pSoe
)
{
PFLCN pFlcn = ENG_GET_FLCN(pSoe);
// POBJMC pMc = GPU_GET_MC(device);
NVSWITCH_TIMEOUT timeout;
nvswitch_timeout_create(NVSWITCH_INTERVAL_1SEC_IN_NS * 5, &timeout);
while (!pFlcn->bOSReady && !nvswitch_timeout_check(&timeout))
{
// Once interrupt handling is ready, might need to replace this with
//mcServiceSingle_HAL(device, pMc, MC_ENGINE_IDX_SOE, NV_FALSE);
soeService_HAL(device, pSoe);
nvswitch_os_sleep(1);
}
if (!pFlcn->bOSReady)
{
NVSWITCH_PRINT(device, ERROR,
"%s Timeout while waiting for SOE bootup\n",
__FUNCTION__);
NVSWITCH_ASSERT(0);
return NV_ERR_TIMEOUT;
}
return NV_OK;
}
/*!
* @brief Retrieves a pointer to the engine specific SEQ_INFO structure.
*
@@ -585,15 +189,10 @@ soeSetupHal
pHal = pSoe->base.pHal;
pParentHal = (flcnable_hal *)pHal;
//set any functions we want to override
pParentHal->handleInitEvent = _soeHandleInitEvent_IMPL;
pParentHal->ememCopyTo = _soeEmemCopyTo_IMPL;
pParentHal->ememCopyFrom = _soeEmemCopyFrom_IMPL;
pParentHal->queueSeqInfoGet = _soeQueueSeqInfoGet_IMPL;
pParentHal->queueCmdValidate = _soeQueueCmdValidate_IMPL;
//set any functions specific to SOE
pHal->processMessages = _soeProcessMessagesPreInit_IMPL;
pHal->waitForInitAck = _soeWaitForInitAck_IMPL;
}
SOE *