summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrad Beckmann <Brad.Beckmann@amd.com>2011-03-19 14:17:48 -0700
committerBrad Beckmann <Brad.Beckmann@amd.com>2011-03-19 14:17:48 -0700
commit541fa1091a42b5148bc98d25ca50f9206226e025 (patch)
tree7849da55add21f381d5d7f20303f705aa5eaac44 /src
parentd1cecc22417abfa05c77bc5945cf52cb46352fdd (diff)
downloadgem5-541fa1091a42b5148bc98d25ca50f9206226e025.tar.xz
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.
Diffstat (limited to 'src')
-rw-r--r--src/mem/ruby/system/DMASequencer.cc8
-rw-r--r--src/mem/ruby/system/RubyPort.cc24
2 files changed, 23 insertions, 9 deletions
diff --git a/src/mem/ruby/system/DMASequencer.cc b/src/mem/ruby/system/DMASequencer.cc
index fbaf5f1d1..e8e279043 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 f4bc5c95c..c79154566 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<M5Port*>::iterator i = retryList.begin();
- i != retryList.end(); ++i) {
- (*i)->sendRetry();
- (*i)->onRetryList(false);
- DPRINTF(MemoryAccess,
+ //
+ // 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<M5Port*> curRetryList(retryList);
+
+ retryList.clear();
+ 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();
}
- retryList.clear();
- waitingOnSequencer = false;
}
}