Ruby: dma retry fix

This patch fixes the problem where Ruby would fail to call sendRetry on ports
after it nacked the port.  This patch is particularly helpful for bursty dma
requests which often include several packets.
This commit is contained in:
Brad Beckmann 2011-03-19 14:17:48 -07:00
parent d1cecc2241
commit 541fa1091a
2 changed files with 24 additions and 10 deletions

View file

@ -116,9 +116,13 @@ DMASequencer::issueNext()
assert(m_is_busy == true); assert(m_is_busy == true);
active_request.bytes_completed = active_request.bytes_issued; active_request.bytes_completed = active_request.bytes_issued;
if (active_request.len == active_request.bytes_completed) { if (active_request.len == active_request.bytes_completed) {
DPRINTF(RubyDma, "DMA request completed\n"); //
ruby_hit_callback(active_request.pkt); // Must unset the busy flag before calling back the dma port because
// the callback may cause a previously nacked request to be reissued
//
DPRINTF(RubyDma, "DMA request completed\n");
m_is_busy = false; m_is_busy = false;
ruby_hit_callback(active_request.pkt);
return; return;
} }

View file

@ -305,16 +305,26 @@ RubyPort::ruby_hit_callback(PacketPtr pkt)
// likely has free resources now. // likely has free resources now.
// //
if (waitingOnSequencer) { if (waitingOnSequencer) {
for (std::list<M5Port*>::iterator i = retryList.begin(); //
i != retryList.end(); ++i) { // Record the current list of ports to retry on a temporary list before
(*i)->sendRetry(); // calling sendRetry on those ports. sendRetry will cause an
(*i)->onRetryList(false); // immediate retry, which may result in the ports being put back on the
DPRINTF(MemoryAccess, // list. Therefore we want to clear the retryList before calling
"Sequencer may now be free. SendRetry to port %s\n", // sendRetry.
(*i)->name()); //
} std::list<M5Port*> curRetryList(retryList);
retryList.clear(); retryList.clear();
waitingOnSequencer = false; waitingOnSequencer = false;
for (std::list<M5Port*>::iterator i = curRetryList.begin();
i != curRetryList.end(); ++i) {
DPRINTF(RubyPort,
"Sequencer may now be free. SendRetry to port %s\n",
(*i)->name());
(*i)->onRetryList(false);
(*i)->sendRetry();
}
} }
} }