diff --git a/src/mem/ruby/system/DMASequencer.cc b/src/mem/ruby/system/DMASequencer.cc index fbaf5f1d14..e8e2790430 100644 --- a/src/mem/ruby/system/DMASequencer.cc +++ b/src/mem/ruby/system/DMASequencer.cc @@ -116,9 +116,13 @@ DMASequencer::issueNext() assert(m_is_busy == true); active_request.bytes_completed = active_request.bytes_issued; 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; + ruby_hit_callback(active_request.pkt); return; } diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index f4bc5c95ca..c791545667 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -305,16 +305,26 @@ RubyPort::ruby_hit_callback(PacketPtr pkt) // likely has free resources now. // if (waitingOnSequencer) { - for (std::list::iterator i = retryList.begin(); - i != retryList.end(); ++i) { - (*i)->sendRetry(); - (*i)->onRetryList(false); - DPRINTF(MemoryAccess, - "Sequencer may now be free. SendRetry to port %s\n", - (*i)->name()); - } + // + // Record the current list of ports to retry on a temporary list before + // calling sendRetry on those ports. sendRetry will cause an + // immediate retry, which may result in the ports being put back on the + // list. Therefore we want to clear the retryList before calling + // sendRetry. + // + std::list curRetryList(retryList); + retryList.clear(); waitingOnSequencer = false; + + for (std::list::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(); + } } }