From 7a83c50a597f73f302ab5fcf372faa35c56a1b06 Mon Sep 17 00:00:00 2001 From: Ali Saidi Date: Tue, 1 Jul 2008 10:30:08 -0400 Subject: 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. --- src/dev/i8254xGBe.cc | 22 +++++++++++++++------- src/dev/i8254xGBe.hh | 1 + 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'src/dev') 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); 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); -- cgit v1.2.3