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;
}
// 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;
}
}