diff options
author | Ali Saidi <saidi@eecs.umich.edu> | 2008-07-01 10:30:08 -0400 |
---|---|---|
committer | Ali Saidi <saidi@eecs.umich.edu> | 2008-07-01 10:30:08 -0400 |
commit | 7a83c50a597f73f302ab5fcf372faa35c56a1b06 (patch) | |
tree | c778b2a163b1dd4aae1c349e239dafa3fc4c8877 /src/dev/i8254xGBe.cc | |
parent | a4a7a09e9622d6ad1ca91a4df253b9768c73de90 (diff) | |
download | gem5-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.
Diffstat (limited to 'src/dev/i8254xGBe.cc')
-rw-r--r-- | src/dev/i8254xGBe.cc | 22 |
1 files changed, 15 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 §ion) UNSERIALIZE_SCALAR(eeDataBits); UNSERIALIZE_SCALAR(eeOpcode); UNSERIALIZE_SCALAR(eeAddr); + UNSERIALIZE_SCALAR(lastInterrupt); UNSERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE); rxFifo.unserialize("rxfifo", cp, section); |