Fix a few bugs in the receive state machine. In doing back to tracking
authorNathan Binkert <binkertn@umich.edu>
Fri, 30 Jul 2004 15:29:45 +0000 (11:29 -0400)
committerNathan Binkert <binkertn@umich.edu>
Fri, 30 Jul 2004 15:29:45 +0000 (11:29 -0400)
whether or not the state machine is enabled rather than tracking the
specific instance of trying to halt the state machine.

dev/ns_gige.cc:
    change back to tracking the state machine's enableness instead of
    whether or not it is trying to halt.  Also fix a major bug that
    would cause the NIC to drop packets when the rx state machine was
    idle, but enabled.
    Fix a couple other bugs in the state machine where the idle interrupt
    would happen at the wrong time.
    Add a warning to deal with improper values of intrTick
dev/ns_gige.hh:
    We need to keep track of whether the state machine is enabled
    or not separately from the control register since the bits don't
    always reflect the truth.

--HG--
extra : convert_revision : 20056b225fa62a0744473babfd693506aa5f29b2

dev/ns_gige.cc
dev/ns_gige.hh

index 27cda69da48125dd7819edcfd32d0473dc9dda89..331966f9c4bb29304cc8818fd7e9e806a0685478 100644 (file)
@@ -108,10 +108,10 @@ NSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay,
     : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t), ioEnable(false),
       maxTxFifoSize(tx_fifo_size), maxRxFifoSize(rx_fifo_size),
       txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
-      txXferLen(0), rxXferLen(0), txState(txIdle), CTDD(false),
-      txFifoAvail(tx_fifo_size), txHalt(false),
+      txXferLen(0), rxXferLen(0), txState(txIdle), txEnable(false),
+      CTDD(false), txFifoAvail(tx_fifo_size),
       txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
-      CRDD(false), rxPktBytes(0), rxFifoCnt(0), rxHalt(false),
+      rxEnable(false), CRDD(false), rxPktBytes(0), rxFifoCnt(0),
       rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
       rxDmaReadEvent(this), rxDmaWriteEvent(this),
       txDmaReadEvent(this), txDmaWriteEvent(this),
@@ -586,24 +586,23 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
         switch (daddr) {
           case CR:
             regs.command = reg;
-            if ((reg & (CR_TXE | CR_TXD)) == (CR_TXE | CR_TXD)) {
-                txHalt = true;
+            if (reg & CR_TXD) {
+                txEnable = false;
             } else if (reg & CR_TXE) {
-                //the kernel is enabling the transmit machine
+                txEnable = true;
+
+                // the kernel is enabling the transmit machine
                 if (txState == txIdle)
                     txKick();
-            } else if (reg & CR_TXD) {
-                txHalt = true;
             }
 
-            if ((reg & (CR_RXE | CR_RXD)) == (CR_RXE | CR_RXD)) {
-                rxHalt = true;
+            if (reg & CR_RXD) {
+                rxEnable = false;
             } else if (reg & CR_RXE) {
-                if (rxState == rxIdle) {
+                rxEnable = true;
+
+                if (rxState == rxIdle)
                     rxKick();
-                }
-            } else if (reg & CR_RXD) {
-                rxHalt = true;
             }
 
             if (reg & CR_TXR)
@@ -777,6 +776,7 @@ NSGigE::write(MemReqPtr &req, const uint8_t *data)
 
           case RXDP:
             regs.rxdp = reg;
+            CRDD = false;
             break;
 
           case RXDP_HI:
@@ -1076,6 +1076,15 @@ NSGigE::cpuIntrPost(Tick when)
     // schedule another.
     // HOWEVER, must be sure that the scheduled intrTick is in the
     // future (this was formerly the source of a bug)
+    /**
+     * @todo this warning should be removed and the intrTick code should
+     * be fixed.
+     */
+    if (intrTick < curTick && intrTick != 0) {
+        warn("intrTick < curTick !!!  intrTick=%d curTick=%d\n",
+             intrTick, curTick);
+        intrTick = 0;
+    }
     assert((intrTick >= curTick) || (intrTick == 0));
     if (when > intrTick && intrTick != 0)
         return;
@@ -1154,11 +1163,10 @@ NSGigE::txReset()
 
     CTDD = false;
     txFifoAvail = maxTxFifoSize;
-    txHalt = false;
+    txEnable = false;;
     txFragPtr = 0;
     assert(txDescCnt == 0);
     txFifo.clear();
-    regs.command &= ~CR_TXE;
     txState = txIdle;
     assert(txDmaState == dmaIdle);
 }
@@ -1171,12 +1179,11 @@ NSGigE::rxReset()
     CRDD = false;
     assert(rxPktBytes == 0);
     rxFifoCnt = 0;
-    rxHalt = false;
+    rxEnable = false;
     rxFragPtr = 0;
     assert(rxDescCnt == 0);
     assert(rxDmaState == dmaIdle);
     rxFifo.clear();
-    regs.command &= ~CR_RXE;
     rxState = rxIdle;
 }
 
@@ -1340,7 +1347,7 @@ NSGigE::rxKick()
     // an event and come back to this loop.
     switch (rxState) {
       case rxIdle:
-        if (!regs.command & CR_RXE) {
+        if (!rxEnable) {
             DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
             goto exit;
         }
@@ -1395,7 +1402,9 @@ NSGigE::rxKick()
                 rxDescCache.extsts);
 
         if (rxDescCache.cmdsts & CMDSTS_OWN) {
+            devIntrPost(ISR_RXIDLE);
             rxState = rxIdle;
+            goto exit;
         } else {
             rxState = rxFifoBlock;
             rxFragPtr = rxDescCache.bufptr;
@@ -1566,18 +1575,20 @@ NSGigE::rxKick()
         if (rxDescCache.cmdsts & CMDSTS_INTR)
             devIntrPost(ISR_RXDESC);
 
-        if (rxHalt) {
+        if (!rxEnable) {
             DPRINTF(EthernetSM, "Halting the RX state machine\n");
             rxState = rxIdle;
-            rxHalt = false;
+            goto exit;
         } else
             rxState = rxAdvance;
         break;
 
       case rxAdvance:
         if (rxDescCache.link == 0) {
+            devIntrPost(ISR_RXIDLE);
             rxState = rxIdle;
-            return;
+            CRDD = true;
+            goto exit;
         } else {
             rxState = rxDescRead;
             regs.rxdp = rxDescCache.link;
@@ -1601,12 +1612,6 @@ NSGigE::rxKick()
     DPRINTF(EthernetSM, "entering next rx state = %s\n",
             NsRxStateStrings[rxState]);
 
-    if (rxState == rxIdle) {
-        regs.command &= ~CR_RXE;
-        devIntrPost(ISR_RXIDLE);
-        return;
-    }
-
     goto next;
 
   exit:
@@ -1805,7 +1810,7 @@ NSGigE::txKick()
 
     switch (txState) {
       case txIdle:
-        if (!regs.command & CR_TXE) {
+        if (!txEnable) {
             DPRINTF(EthernetSM, "Transmit disabled.  Nothing to do.\n");
             goto exit;
         }
@@ -1865,7 +1870,9 @@ NSGigE::txKick()
             txFragPtr = txDescCache.bufptr;
             txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK;
         } else {
+            devIntrPost(ISR_TXIDLE);
             txState = txIdle;
+            goto exit;
         }
         break;
 
@@ -1948,10 +1955,10 @@ NSGigE::txKick()
                 transmit();
                 txPacket = 0;
 
-                if (txHalt) {
+                if (!txEnable) {
                     DPRINTF(EthernetSM, "halting TX state machine\n");
                     txState = txIdle;
-                    txHalt = false;
+                    goto exit;
                 } else
                     txState = txAdvance;
 
@@ -2004,16 +2011,17 @@ NSGigE::txKick()
         if (txDmaState != dmaIdle)
             goto exit;
 
-        if (txDescCache.cmdsts & CMDSTS_INTR) {
+        if (txDescCache.cmdsts & CMDSTS_INTR)
             devIntrPost(ISR_TXDESC);
-        }
 
         txState = txAdvance;
         break;
 
       case txAdvance:
         if (txDescCache.link == 0) {
+            devIntrPost(ISR_TXIDLE);
             txState = txIdle;
+            goto exit;
         } else {
             txState = txDescRead;
             regs.txdp = txDescCache.link;
@@ -2036,12 +2044,6 @@ NSGigE::txKick()
     DPRINTF(EthernetSM, "entering next tx state=%s\n",
             NsTxStateStrings[txState]);
 
-    if (txState == txIdle) {
-        regs.command &= ~CR_TXE;
-        devIntrPost(ISR_TXIDLE);
-        return;
-    }
-
     goto next;
 
   exit:
@@ -2123,7 +2125,7 @@ NSGigE::recvPacket(PacketPtr packet)
     DPRINTF(Ethernet, "\n\nReceiving packet from wire, rxFifoAvail=%d\n",
             maxRxFifoSize - rxFifoCnt);
 
-    if (rxState == rxIdle) {
+    if (!rxEnable) {
         DPRINTF(Ethernet, "receive disabled...packet dropped\n");
         interface->recvDone();
         return true;
@@ -2388,9 +2390,9 @@ NSGigE::serialize(ostream &os)
      */
     int txState = this->txState;
     SERIALIZE_SCALAR(txState);
+    SERIALIZE_SCALAR(txEnable);
     SERIALIZE_SCALAR(CTDD);
     SERIALIZE_SCALAR(txFifoAvail);
-    SERIALIZE_SCALAR(txHalt);
     SERIALIZE_SCALAR(txFragPtr);
     SERIALIZE_SCALAR(txDescCnt);
     int txDmaState = this->txDmaState;
@@ -2401,10 +2403,10 @@ NSGigE::serialize(ostream &os)
      */
     int rxState = this->rxState;
     SERIALIZE_SCALAR(rxState);
+    SERIALIZE_SCALAR(rxEnable);
     SERIALIZE_SCALAR(CRDD);
     SERIALIZE_SCALAR(rxPktBytes);
     SERIALIZE_SCALAR(rxFifoCnt);
-    SERIALIZE_SCALAR(rxHalt);
     SERIALIZE_SCALAR(rxDescCnt);
     int rxDmaState = this->rxDmaState;
     SERIALIZE_SCALAR(rxDmaState);
@@ -2550,9 +2552,9 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
     int txState;
     UNSERIALIZE_SCALAR(txState);
     this->txState = (TxState) txState;
+    UNSERIALIZE_SCALAR(txEnable);
     UNSERIALIZE_SCALAR(CTDD);
     UNSERIALIZE_SCALAR(txFifoAvail);
-    UNSERIALIZE_SCALAR(txHalt);
     UNSERIALIZE_SCALAR(txFragPtr);
     UNSERIALIZE_SCALAR(txDescCnt);
     int txDmaState;
@@ -2565,10 +2567,10 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
     int rxState;
     UNSERIALIZE_SCALAR(rxState);
     this->rxState = (RxState) rxState;
+    UNSERIALIZE_SCALAR(rxEnable);
     UNSERIALIZE_SCALAR(CRDD);
     UNSERIALIZE_SCALAR(rxPktBytes);
     UNSERIALIZE_SCALAR(rxFifoCnt);
-    UNSERIALIZE_SCALAR(rxHalt);
     UNSERIALIZE_SCALAR(rxDescCnt);
     int rxDmaState;
     UNSERIALIZE_SCALAR(rxDmaState);
index c326d0921f3c36f92a188a36ea5268bdff6a5060..82f640db176b61dfd4f186c13443ee9d7ec01d2d 100644 (file)
@@ -186,6 +186,8 @@ class NSGigE : public PciDev
 
     /* tx State Machine */
     TxState txState;
+    bool txEnable;
+
     /** Current Transmit Descriptor Done */
     bool CTDD;
     /** current amt of free space in txDataFifo in bytes */
@@ -200,6 +202,8 @@ class NSGigE : public PciDev
 
     /** rx State Machine */
     RxState rxState;
+    bool rxEnable;
+
     /** Current Receive Descriptor Done */
     bool CRDD;
     /** num of bytes in the current packet being drained from rxDataFifo */