tulip bug, alternative fix (untested)

From: Wolfgang Walter (wolfgang.walter@stusta.mhn.de)
Date: Fri Nov 26 1999 - 20:16:43 EST


Hi Edward,

my patch (corrected patch 2) does work here.

Now I implemented another approach which may be more elegant and better.

It works under normal condition without problems. If it works under the
hang-condition I could not verify yet. Try out :-).

Greetings,

Wolfgang Walter

--- 2.2.14pre4/drivers/net/tulip.c Fri Nov 5 18:02:35 1999
+++ 2.2.14pre4-m/drivers/net/tulip.c Sat Nov 27 02:03:32 1999
@@ -530,6 +530,8 @@
         int cur_index; /* Current media index. */
         int saved_if_port;
         unsigned char pci_bus, pci_devfn;
+ int ttimer;
+ int susp_rx;
         int pad0, pad1; /* Used for 8-byte alignment */
 };
 
@@ -2484,6 +2486,8 @@
         tp->tx_full = 0;
         tp->cur_rx = tp->cur_tx = 0;
         tp->dirty_rx = tp->dirty_tx = 0;
+ tp->susp_rx = 0;
+ tp->ttimer = 0;
 
         for (i = 0; i < RX_RING_SIZE; i++) {
                 tp->rx_ring[i].status = 0x00000000;
@@ -2578,6 +2582,8 @@
         struct tulip_private *tp = (struct tulip_private *)dev->priv;
         long ioaddr = dev->base_addr;
         int csr5, work_budget = max_interrupt_work;
+ int entry;
+ int missed;
 
 #if defined(__i386__) && defined(SMP_CHECK)
         if (test_and_set_bit(0, (void*)&dev->interrupt)) {
@@ -2594,7 +2600,7 @@
         }
         dev->interrupt = 1;
 #endif
-
+
         do {
                 csr5 = inl(ioaddr + CSR5);
                 /* Acknowledge all of the current interrupt sources ASAP. */
@@ -2607,7 +2613,10 @@
                 if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
                         break;
 
- if (csr5 & (RxIntr | RxNoBuf))
+ if (csr5 & RxNoBuf)
+ tp->susp_rx = 1;
+
+ if (csr5 & RxIntr)
                         work_budget -= tulip_rx(dev);
 
                 if (csr5 & (TxNoBuf | TxDied | TxIntr)) {
@@ -2708,6 +2717,7 @@
                                         printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n",
                                                    dev->name, csr5);
                                 outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
+ tp->ttimer = 0;
                         }
                         if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) {
                                 if (tp->link_change)
@@ -2726,9 +2736,34 @@
                         outl(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt,
                                  ioaddr + CSR7);
                         outl(12, ioaddr + CSR11);
+ tp->ttimer = 1;
                         break;
                 }
         } while (1);
+
+
+ /* if in suspend mode: try to get an skb */
+ entry = tp->cur_rx % RX_RING_SIZE;
+ if (tp->susp_rx) {
+ tulip_rx(dev);
+ tp->susp_rx = 0;
+ }
+
+ /* check if we card is in suspend mode */
+ if (tp->rx_skbuff[entry] == NULL) {
+ tp->susp_rx = 1;
+ if (tp->ttimer == 0 || (inl(ioaddr + CSR11) & 0xffff) == 0) {
+ outl(tulip_tbl[tp->chip_id].valid_intrs | TimerInt,
+ ioaddr + CSR7);
+ outl(TimerInt, ioaddr + CSR5);
+ outl(12, ioaddr + CSR11);
+ tp->ttimer = 1;
+ }
+ }
+
+ if ((missed = inl(ioaddr + CSR8) & 0x1ffff)) {
+ tp->stats.rx_dropped += missed & 0x10000 ? 0x10000 : missed;
+ }
 
         if (tulip_debug > 4)
                 printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",



This archive was generated by hypermail 2b29 : Wed Jan 12 2000 - 12:00:16 EST