Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions src/common/unix/nvidia-push/src/nvidia-push.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ static NvBool nvWriteGpEntry(

NvU32 nextGpPut;
NvU32 *gpPointer;
NvU64 baseTime, currentTime;
const NvU32 entriesNeeded = NV_PUSH_NUM_GPFIFO_ENTRIES_PER_KICKOFF;
NvPushDevicePtr pDevice = push_buffer->pDevice;

Expand All @@ -359,11 +360,21 @@ static NvBool nvWriteGpEntry(
nvAssert((nextGpPut % 2) == 0);

// Wait for a free entry in the buffer
while (nextGpPut == ReadGpGetOffset(push_buffer)) {
for (baseTime = currentTime = nvPushImportGetMilliSeconds(pDevice);
nextGpPut == ReadGpGetOffset(push_buffer);
currentTime = nvPushImportGetMilliSeconds(pDevice)) {

if (nvPushCheckChannelError(push_buffer)) {
nvAssert(!"A channel error occurred in nvWriteGpEntry()");
return FALSE;
}

if (currentTime > (baseTime + NV_PUSH_NOTIFIER_SHORT_TIMEOUT) &&
!push_buffer->noTimeout) {
nvPushImportLogError(pDevice,
"Timed out waiting for a free GPFIFO entry.");
return FALSE;
}
}
gpPointer[0] = gpEntry0;
gpPointer[1] = gpEntry1;
Expand Down Expand Up @@ -616,6 +627,7 @@ void __nvPushMakeRoom(NvPushChannelPtr push_buffer, NvU32 count)
NvU32 getOffset;
NvU32 putOffset;
NvBool fenceToEnd = FALSE;
NvU64 baseTime, currentTime;

putOffset = (NvU32) ((char *)push_buffer->main.buffer -
(char *)push_buffer->main.base);
Expand All @@ -628,14 +640,37 @@ void __nvPushMakeRoom(NvPushChannelPtr push_buffer, NvU32 count)
}
nvAssert(putOffset == push_buffer->main.putOffset);

while (count >= push_buffer->main.freeDwords) {
for (baseTime = currentTime =
nvPushImportGetMilliSeconds(push_buffer->pDevice);
count >= push_buffer->main.freeDwords;
currentTime = nvPushImportGetMilliSeconds(push_buffer->pDevice)) {

if (nvPushCheckChannelError(push_buffer)) {
nvAssert(!"A channel error occurred in __nvPushMakeRoom()");
// Unlike with non-gpfifo channels, RC recovery can't reset GET to
// 0 so we need to continue as if we just started waiting for space.
return __nvPushMakeRoom(push_buffer, count);
}

if (currentTime > (baseTime + NV_PUSH_NOTIFIER_SHORT_TIMEOUT) &&
!push_buffer->noTimeout) {
// GET has stopped advancing and no channel error was raised, so no
// room will ever free up. Don't spin forever: this function is
// void and its callers write unconditionally once it returns, so
// give them in-bounds space by wrapping the write pointer back to
// the start of the pushbuffer and declaring it free. Each method
// write is asserted smaller than sizeInBytes/8, so a full-buffer
// grant is always enough. The methods land only in this channel's
// own pushbuffer, which the stalled GPU never reads; the ensuing
// kickoff fails and the caller (e.g. DIFR prefetch) gives up.
nvPushImportLogError(push_buffer->pDevice,
"Timed out waiting for room in the pushbuffer.");
push_buffer->main.putOffset = 0;
push_buffer->main.buffer = push_buffer->main.base;
push_buffer->main.freeDwords = push_buffer->main.sizeInBytes >> 2;
return;
}

getOffset = nvPushReadGetOffset(push_buffer, TRUE);
nvAssert(getOffset <= push_buffer->main.sizeInBytes);

Expand Down