summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Saidi <saidi@eecs.umich.edu>2008-07-01 10:30:08 -0400
committerAli Saidi <saidi@eecs.umich.edu>2008-07-01 10:30:08 -0400
commit7a83c50a597f73f302ab5fcf372faa35c56a1b06 (patch)
treec778b2a163b1dd4aae1c349e239dafa3fc4c8877
parenta4a7a09e9622d6ad1ca91a4df253b9768c73de90 (diff)
downloadgem5-7a83c50a597f73f302ab5fcf372faa35c56a1b06.tar.xz
Fix cases where RADV interrupt timer is used and make ITR interrupt moderation not always delay if no interrupts have been posted for the ITR value.
-rw-r--r--src/dev/i8254xGBe.cc22
-rw-r--r--src/dev/i8254xGBe.hh1
2 files changed, 16 insertions, 7 deletions
diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc
index 3b1970432..76e11b752 100644
--- a/src/dev/i8254xGBe.cc
+++ b/src/dev/i8254xGBe.cc
@@ -60,7 +60,8 @@ IGbE::IGbE(const Params *p)
txTick(false), txFifoTick(false), rxDmaPacket(false), rdtrEvent(this), radvEvent(this),
tadvEvent(this), tidvEvent(this), tickEvent(this), interEvent(this),
rxDescCache(this, name()+".RxDesc", p->rx_desc_cache_size),
- txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size), clock(p->clock)
+ txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size),
+ clock(p->clock), lastInterrupt(0)
{
etherInt = new IGbEInt(name() + ".int", this);
@@ -580,17 +581,22 @@ IGbE::postInterrupt(IntTypes t, bool now)
return;
regs.icr = regs.icr() | t;
- if (regs.itr.interval() == 0 || now) {
+
+ Tick itr_interval = Clock::Int::ns * 256 * regs.itr.interval();
+
+ if (regs.itr.interval() == 0 || now || lastInterrupt + itr_interval <= curTick) {
if (interEvent.scheduled()) {
interEvent.deschedule();
}
postedInterrupts++;
cpuPostInt();
} else {
- DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for %d ticks\n",
- Clock::Int::ns * 256 * regs.itr.interval());
+ Tick int_time = lastInterrupt + itr_interval;
+ assert(int_time > 0);
+ DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for tick %d\n",
+ int_time);
if (!interEvent.scheduled()) {
- interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval());
+ interEvent.schedule(int_time);
}
}
}
@@ -789,7 +795,7 @@ IGbE::RxDescCache::pktComplete()
igbe->intClock(),true);
}
- if (igbe->regs.radv.idv() && igbe->regs.rdtr.delay()) {
+ if (igbe->regs.radv.idv()) {
DPRINTF(EthernetSM, "RXS: Scheduling ADV for %d\n",
igbe->regs.radv.idv() * igbe->intClock());
if (!igbe->radvEvent.scheduled()) {
@@ -799,7 +805,7 @@ IGbE::RxDescCache::pktComplete()
}
// if neither radv or rdtr, maybe itr is set...
- if (!igbe->regs.rdtr.delay()) {
+ if (!igbe->regs.rdtr.delay() && !igbe->regs.radv.idv()) {
DPRINTF(EthernetSM, "RXS: Receive interrupt delay disabled, posting IT_RXT\n");
igbe->postInterrupt(IT_RXT);
}
@@ -1446,6 +1452,7 @@ IGbE::serialize(std::ostream &os)
SERIALIZE_SCALAR(eeDataBits);
SERIALIZE_SCALAR(eeOpcode);
SERIALIZE_SCALAR(eeAddr);
+ SERIALIZE_SCALAR(lastInterrupt);
SERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE);
rxFifo.serialize("rxfifo", os);
@@ -1497,6 +1504,7 @@ IGbE::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(eeDataBits);
UNSERIALIZE_SCALAR(eeOpcode);
UNSERIALIZE_SCALAR(eeAddr);
+ UNSERIALIZE_SCALAR(lastInterrupt);
UNSERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE);
rxFifo.unserialize("rxfifo", cp, section);
diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh
index 7957eb515..a69793bd4 100644
--- a/src/dev/i8254xGBe.hh
+++ b/src/dev/i8254xGBe.hh
@@ -622,6 +622,7 @@ class IGbE : public EtherDevice
virtual EtherInt *getEthPort(const std::string &if_name, int idx);
Tick clock;
+ Tick lastInterrupt;
inline Tick ticks(int numCycles) const { return numCycles * clock; }
virtual Tick read(PacketPtr pkt);