some more fixes... non-tso stuff seems to work
authorAli Saidi <saidi@eecs.umich.edu>
Wed, 28 Mar 2007 00:44:21 +0000 (20:44 -0400)
committerAli Saidi <saidi@eecs.umich.edu>
Wed, 28 Mar 2007 00:44:21 +0000 (20:44 -0400)
--HG--
extra : convert_revision : da604d20443376d04826397d0aaff0bdd744053b

src/dev/i8254xGBe.cc
src/dev/i8254xGBe.hh
src/dev/i8254xGBe_defs.hh

index c38a9e873d2374c78138b014515f50fe57d5dd9e..60ea45a605f76eaa59ad35be1f83e1b47be689ce 100644 (file)
@@ -57,8 +57,8 @@ using namespace Net;
 IGbE::IGbE(Params *p)
     : PciDev(p), etherInt(NULL),  useFlowControl(p->use_flow_control),
       rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxTick(false),
-      txTick(false), rdtrEvent(this), radvEvent(this), tadvEvent(this),
-      tidvEvent(this), tickEvent(this), interEvent(this),
+      txTick(false), txFifoTick(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)
 {
@@ -223,6 +223,7 @@ IGbE::read(PacketPtr pkt)
         pkt->set<uint32_t>(regs.rdtr());
         if (regs.rdtr.fpd()) {
             rxDescCache.writeback(0);
+            DPRINTF(EthernetIntr, "Posting interrupt because of RDTR.FPD write\n");
             postInterrupt(IT_RXT);
             regs.rdtr.fpd(0);
         }
@@ -411,6 +412,7 @@ IGbE::write(PacketPtr pkt)
         regs.itr = val;
         break;
       case REG_ICS:
+        DPRINTF(EthernetIntr, "Posting interrupt because of ICS write\n");
         postInterrupt((IntTypes)val);
         break;
        case REG_IMS:
@@ -429,6 +431,7 @@ IGbE::write(PacketPtr pkt)
         regs.rctl = val;
         if (regs.rctl.rst()) {
             rxDescCache.reset();
+            DPRINTF(EthernetSM, "RXS: Got RESET!\n");
             rxFifo.clear();
             regs.rctl.rst(0);
         }
@@ -568,8 +571,8 @@ IGbE::postInterrupt(IntTypes t, bool now)
         } else {
            DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for %d ticks\n",
                     Clock::Int::ns * 256 * regs.itr.interval());
-           assert(!interEvent.scheduled());
-           interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval());
+           if (!interEvent.scheduled())
+               interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval());
         }
     }
 }
@@ -676,39 +679,39 @@ IGbE::RxDescCache::pktComplete()
     // no support for anything but starting at 0
     assert(igbe->regs.rxcsum.pcss() == 0);
 
-    DPRINTF(EthernetDesc, "RxDesc: Packet written to memory updating Descriptor\n");
+    DPRINTF(EthernetDesc, "Packet written to memory updating Descriptor\n");
 
     uint8_t status = RXDS_DD | RXDS_EOP;
     uint8_t err = 0;
     IpPtr ip(pktPtr);
     if (ip) {
         if (igbe->regs.rxcsum.ipofld()) {
-            DPRINTF(EthernetDesc, "RxDesc: Checking IP checksum\n");
+            DPRINTF(EthernetDesc, "Checking IP checksum\n");
             status |= RXDS_IPCS;
             desc->csum = htole(cksum(ip));
             if (cksum(ip) != 0) {
                 err |= RXDE_IPE;
-                DPRINTF(EthernetDesc, "RxDesc: Checksum is bad!!\n");
+                DPRINTF(EthernetDesc, "Checksum is bad!!\n");
             }
         }
         TcpPtr tcp(ip);
         if (tcp && igbe->regs.rxcsum.tuofld()) {
-            DPRINTF(EthernetDesc, "RxDesc: Checking TCP checksum\n");
+            DPRINTF(EthernetDesc, "Checking TCP checksum\n");
             status |= RXDS_TCPCS;
             desc->csum = htole(cksum(tcp));
             if (cksum(tcp) != 0) {
-                DPRINTF(EthernetDesc, "RxDesc: Checksum is bad!!\n");
+                DPRINTF(EthernetDesc, "Checksum is bad!!\n");
                 err |= RXDE_TCPE;
             }
         }
 
         UdpPtr udp(ip);
         if (udp && igbe->regs.rxcsum.tuofld()) {
-            DPRINTF(EthernetDesc, "RxDesc: Checking UDP checksum\n");
+            DPRINTF(EthernetDesc, "Checking UDP checksum\n");
             status |= RXDS_UDPCS;
             desc->csum = htole(cksum(udp));
             if (cksum(tcp) != 0) {
-                DPRINTF(EthernetDesc, "RxDesc: Checksum is bad!!\n");
+                DPRINTF(EthernetDesc, "Checksum is bad!!\n");
                 err |= RXDE_TCPE;
             }
         }
@@ -748,10 +751,12 @@ IGbE::RxDescCache::pktComplete()
 
     // If the packet is small enough, interrupt appropriately
     // I wonder if this is delayed or not?!
-    if (pktPtr->length <= igbe->regs.rsrpd.idv())
+    if (pktPtr->length <= igbe->regs.rsrpd.idv()) {
+        DPRINTF(EthernetSM, "RXS: Posting IT_SRPD beacuse small packet received\n");
         igbe->postInterrupt(IT_SRPD);
+    }
 
-    DPRINTF(EthernetDesc, "RxDesc: Processing of this descriptor complete\n");
+    DPRINTF(EthernetDesc, "Processing of this descriptor complete\n");
     unusedCache.pop_front();
     usedCache.push_back(desc);
     pktPtr = NULL;
@@ -792,10 +797,10 @@ IGbE::TxDescCache::getPacketSize()
 
     TxDesc *desc;
 
-    DPRINTF(EthernetDesc, "TxDesc: Starting processing of descriptor\n");
+    DPRINTF(EthernetDesc, "Starting processing of descriptor\n");
 
     while (unusedCache.size() && TxdOp::isContext(unusedCache.front())) {
-        DPRINTF(EthernetDesc, "TxDesc: Got context descriptor type... skipping\n");
+        DPRINTF(EthernetDesc, "Got context descriptor type... skipping\n");
 
         // I think we can just ignore these for now?
         desc = unusedCache.front();
@@ -813,7 +818,7 @@ IGbE::TxDescCache::getPacketSize()
     if (!unusedCache.size())
         return -1;
 
-    DPRINTF(EthernetDesc, "TxDesc: Next TX packet is %d bytes\n",
+    DPRINTF(EthernetDesc, "Next TX packet is %d bytes\n",
             TxdOp::getLen(unusedCache.front()));
 
     return TxdOp::getLen(unusedCache.front());
@@ -833,7 +838,7 @@ IGbE::TxDescCache::getPacketData(EthPacketPtr p)
 
     pktWaiting = true;
 
-    DPRINTF(EthernetDesc, "TxDesc: Starting DMA of packet\n");
+    DPRINTF(EthernetDesc, "Starting DMA of packet\n");
     igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)),
             TxdOp::getLen(desc), &pktEvent, p->data + hLen);
 
@@ -848,7 +853,7 @@ IGbE::TxDescCache::pktComplete()
     assert(unusedCache.size());
     assert(pktPtr);
 
-    DPRINTF(EthernetDesc, "TxDesc: DMA of packet complete\n");
+    DPRINTF(EthernetDesc, "DMA of packet complete\n");
 
 
     desc = unusedCache.front();
@@ -865,7 +870,7 @@ IGbE::TxDescCache::pktComplete()
         pktWaiting = false;
         pktPtr = NULL;
 
-        DPRINTF(EthernetDesc, "TxDesc: Partial Packet Descriptor Done\n");
+        DPRINTF(EthernetDesc, "Partial Packet Descriptor Done\n");
         return;
     }
 
@@ -888,33 +893,33 @@ IGbE::TxDescCache::pktComplete()
 
     // Checksums are only ofloaded for new descriptor types
     if (TxdOp::isData(desc) && ( TxdOp::ixsm(desc) || TxdOp::txsm(desc)) ) {
-        DPRINTF(EthernetDesc, "TxDesc: Calculating checksums for packet\n");
+        DPRINTF(EthernetDesc, "Calculating checksums for packet\n");
         IpPtr ip(pktPtr);
         if (TxdOp::ixsm(desc)) {
             ip->sum(0);
             ip->sum(cksum(ip));
-            DPRINTF(EthernetDesc, "TxDesc: Calculated IP checksum\n");
+            DPRINTF(EthernetDesc, "Calculated IP checksum\n");
         }
        if (TxdOp::txsm(desc)) {
            if (isTcp) {
                 TcpPtr tcp(ip);
                 tcp->sum(0);
                 tcp->sum(cksum(tcp));
-                DPRINTF(EthernetDesc, "TxDesc: Calculated TCP checksum\n");
+                DPRINTF(EthernetDesc, "Calculated TCP checksum\n");
            } else {
                 UdpPtr udp(ip);
                 udp->sum(0);
                 udp->sum(cksum(udp));
-                DPRINTF(EthernetDesc, "TxDesc: Calculated UDP checksum\n");
+                DPRINTF(EthernetDesc, "Calculated UDP checksum\n");
            }
         }
     }
 
     if (TxdOp::ide(desc)) {
         // Deal with the rx timer interrupts
-        DPRINTF(EthernetDesc, "TxDesc: Descriptor had IDE set\n");
+        DPRINTF(EthernetDesc, "Descriptor had IDE set\n");
         if (igbe->regs.tidv.idv()) {
-            DPRINTF(EthernetDesc, "TxDesc: setting tidv\n");
+            DPRINTF(EthernetDesc, "setting tidv\n");
             if (igbe->tidvEvent.scheduled())
                 igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() *
                         igbe->intClock());
@@ -924,7 +929,7 @@ IGbE::TxDescCache::pktComplete()
         }
 
         if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) {
-            DPRINTF(EthernetDesc, "TxDesc: setting tadv\n");
+            DPRINTF(EthernetDesc, "setting tadv\n");
             if (!igbe->tadvEvent.scheduled())
                 igbe->tadvEvent.schedule(curTick + igbe->regs.tadv.idv() *
                         igbe->intClock());
@@ -940,13 +945,13 @@ IGbE::TxDescCache::pktComplete()
     pktPtr = NULL;
 
     hLen = 0;
-    DPRINTF(EthernetDesc, "TxDesc: Descriptor Done\n");
+    DPRINTF(EthernetDesc, "Descriptor Done\n");
 
     if (igbe->regs.txdctl.wthresh() == 0) {
-        DPRINTF(EthernetDesc, "TxDesc: WTHRESH == 0, writing back descriptor\n");
+        DPRINTF(EthernetDesc, "WTHRESH == 0, writing back descriptor\n");
         writeback(0);
     } else if (igbe->regs.txdctl.wthresh() >= usedCache.size()) {
-        DPRINTF(EthernetDesc, "TxDesc: used > WTHRESH, writing back descriptor\n");
+        DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");
         writeback((igbe->cacheBlockSize()-1)>>4);
     }
 
@@ -998,8 +1003,10 @@ IGbE::txStateMachine()
         bool success;
         DPRINTF(EthernetSM, "TXS: packet placed in TX FIFO\n");
         success = txFifo.push(txPacket);
+        txFifoTick = true;
         assert(success);
         txPacket = NULL;
+        txDescCache.writeback((cacheBlockSize()-1)>>4);
         return;
     }
 
@@ -1021,6 +1028,7 @@ IGbE::txStateMachine()
             txDescCache.writeback(0);
             txTick = false;
             postInterrupt(IT_TXQE, true);
+            return;
         }
 
 
@@ -1038,11 +1046,17 @@ IGbE::txStateMachine()
                     "DMA of next packet\n", size);
             txFifo.reserve(size);
             txDescCache.getPacketData(txPacket);
-        } else {
+        } else if (size <= 0) {
             DPRINTF(EthernetSM, "TXS: No packets to get, writing back used descriptors\n");
             txDescCache.writeback(0);
+        } else {
+            DPRINTF(EthernetSM, "TXS: FIFO full, stopping ticking until space "
+                    "available in FIFO\n");
+            txDescCache.writeback((cacheBlockSize()-1)>>4);
+            txTick = false;
         }
 
+
         return;
     }
 }
@@ -1095,9 +1109,9 @@ IGbE::rxStateMachine()
         }
 
         if (descLeft == 0) {
-            DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing writeback\n");
+            DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing"
+                    " writeback and stopping ticking\n");
             rxDescCache.writeback(0);
-            DPRINTF(EthernetSM, "RXS: No descriptors left, stopping ticking\n");
             rxTick = false;
         }
 
@@ -1119,9 +1133,9 @@ IGbE::rxStateMachine()
         }
 
         if (rxDescCache.descUnused() == 0) {
-            DPRINTF(EthernetSM, "RXS: No descriptors available in cache, stopping ticking\n");
+            DPRINTF(EthernetSM, "RXS: No descriptors available in cache, "
+                    "fetching descriptors and stopping ticking\n");
             rxTick = false;
-            DPRINTF(EthernetSM, "RXS: Fetching descriptors because none available\n");
             rxDescCache.fetchDescriptors();
         }
         return;
@@ -1159,15 +1173,18 @@ void
 IGbE::txWire()
 {
     if (txFifo.empty()) {
+        txFifoTick = false;
         return;
     }
 
-    txTick = true;
 
     if (etherInt->sendPacket(txFifo.front())) {
         DPRINTF(Ethernet, "TxFIFO: Successful transmit, bytes in fifo: %d\n",
                 txFifo.avail());
         txFifo.pop();
+    } else {
+        // We'll get woken up when the packet ethTxDone() gets called
+        txFifoTick = false;
     }
 
 }
@@ -1180,20 +1197,26 @@ IGbE::tick()
     if (rxTick)
         rxStateMachine();
 
-    if (txTick) {
+    if (txTick)
         txStateMachine();
+
+    if (txFifoTick)
         txWire();
-    }
 
-    if (rxTick || txTick)
+
+    if (rxTick || txTick || txFifoTick)
         tickEvent.schedule(curTick + cycles(1));
 }
 
 void
 IGbE::ethTxDone()
 {
-    // restart the state machines if they are stopped
+    // restart the tx state machines if they are stopped
+    // fifo to send another packet
+    // tx sm to put more data into the fifo
+    txFifoTick = true;
     txTick = true;
+
     restartClock();
     DPRINTF(Ethernet, "TxFIFO: Transmission complete\n");
 }
index a2b9f38d58cf2c0e740d4e99947042be7e9b0eeb..3304f0862a57f3a00166b0926243563b486f71cc 100644 (file)
@@ -76,24 +76,44 @@ class IGbE : public PciDev
     // Should to Rx/Tx State machine tick?
     bool rxTick;
     bool txTick;
+    bool txFifoTick;
 
     // Event and function to deal with RDTR timer expiring
-    void rdtrProcess() { rxDescCache.writeback(0); postInterrupt(iGbReg::IT_RXT, true); }
+    void rdtrProcess() {
+        rxDescCache.writeback(0);
+        DPRINTF(EthernetIntr, "Posting RXT interrupt because RDTR timer expired\n");
+        postInterrupt(iGbReg::IT_RXT, true);
+    }
+
     //friend class EventWrapper<IGbE, &IGbE::rdtrProcess>;
     EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent;
 
     // Event and function to deal with RADV timer expiring
-    void radvProcess() { rxDescCache.writeback(0); postInterrupt(iGbReg::IT_RXT, true); }
+    void radvProcess() {
+        rxDescCache.writeback(0);
+        DPRINTF(EthernetIntr, "Posting RXT interrupt because RADV timer expired\n");
+        postInterrupt(iGbReg::IT_RXT, true);
+    }
+
     //friend class EventWrapper<IGbE, &IGbE::radvProcess>;
     EventWrapper<IGbE, &IGbE::radvProcess> radvEvent;
 
     // Event and function to deal with TADV timer expiring
-    void tadvProcess() { postInterrupt(iGbReg::IT_TXDW, true); }
+    void tadvProcess() {
+        txDescCache.writeback(0);
+        DPRINTF(EthernetIntr, "Posting TXDW interrupt because TADV timer expired\n");
+        postInterrupt(iGbReg::IT_TXDW, true);
+    }
+
     //friend class EventWrapper<IGbE, &IGbE::tadvProcess>;
     EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent;
 
     // Event and function to deal with TIDV timer expiring
-    void tidvProcess() { postInterrupt(iGbReg::IT_TXDW, true); };
+    void tidvProcess() {
+        txDescCache.writeback(0);
+        DPRINTF(EthernetIntr, "Posting TXDW interrupt because TIDV timer expired\n");
+        postInterrupt(iGbReg::IT_TXDW, true);
+    }
     //friend class EventWrapper<IGbE, &IGbE::tidvProcess>;
     EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent;
 
@@ -202,8 +222,10 @@ class IGbE : public PciDev
          */
         void areaChanged()
         {
-            if (usedCache.size() > 0 || unusedCache.size() > 0)
+            if (usedCache.size() > 0 || curFetching || wbOut)
                 panic("Descriptor Address, Length or Head changed. Bad\n");
+            reset();
+
         }
 
         void writeback(Addr aMask)
@@ -229,7 +251,7 @@ class IGbE : public PciDev
             moreToWb = false;
             wbAlignment = aMask;
 
-            if (max_to_wb + curHead > descLen()) {
+            if (max_to_wb + curHead >= descLen()) {
                 max_to_wb = descLen() - curHead;
                 moreToWb = true;
                 // this is by definition aligned correctly
@@ -265,10 +287,14 @@ class IGbE : public PciDev
          */
         void fetchDescriptors()
         {
-            size_t max_to_fetch = descTail() - cachePnt;
-            if (max_to_fetch < 0)
+            size_t max_to_fetch;
+
+            if (descTail() >= cachePnt)
+                max_to_fetch = descTail() - cachePnt;
+            else
                 max_to_fetch = descLen() - cachePnt;
 
+
             max_to_fetch = std::min(max_to_fetch, (size - usedCache.size() -
                         unusedCache.size()));
 
@@ -311,8 +337,9 @@ class IGbE : public PciDev
 #endif
 
             cachePnt += curFetching;
-            if (cachePnt > descLen())
-                cachePnt -= descLen();
+            assert(cachePnt <= descLen());
+            if (cachePnt == descLen())
+                cachePnt = 0;
 
             curFetching = 0;
 
@@ -337,8 +364,8 @@ class IGbE : public PciDev
             curHead += wbOut;
             wbOut = 0;
 
-            if (curHead > descLen())
-                curHead = 0;
+            if (curHead >= descLen())
+                curHead -= descLen();
 
             // Update the head
             updateHead(curHead);
@@ -390,6 +417,9 @@ class IGbE : public PciDev
 
             usedCache.clear();
             unusedCache.clear();
+
+            cachePnt = 0;
+
         }
 
      };
index 8538c155b531c83102aab8ffec4f13a1ea5a1f6a..6820b96c4b3c0ca4bcbd3ca268f4ff75b1c6f6d4 100644 (file)
@@ -162,7 +162,7 @@ struct TxDesc {
 
 namespace TxdOp {
 const uint8_t TXD_CNXT = 0x0;
-const uint8_t TXD_DATA = 0x0;
+const uint8_t TXD_DATA = 0x1;
 
 bool isLegacy(TxDesc *d) { return !bits(d->d2,29,29); }
 uint8_t getType(TxDesc *d) { return bits(d->d2, 23,20); }