Messages in this thread Patch in this message | | | Date | Sun, 28 Nov 1999 05:47:59 +0100 | From | Wolfgang Walter <> | Subject | tulip bug, alternative fix, #3 (tested) |
| |
Hi,
this patch works for me. Would be nice if you could confirm it :-). Change compared with my previous one I sent you: TimerInt handling changed.
Thanks,
Wolfgang Walter
--- 2.2.14pre4/drivers/net/tulip.c Fri Nov 5 18:02:35 1999 +++ 2.2.14pre4-m/drivers/net/tulip.c Sun Nov 28 05:59:44 1999 @@ -530,6 +530,9 @@ int cur_index; /* Current media index. */ int saved_if_port; unsigned char pci_bus, pci_devfn; + int ttimer; + int susp_rx; + unsigned long nir; int pad0, pad1; /* Used for 8-byte alignment */ }; @@ -2484,6 +2487,9 @@ 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; + tp->nir = 0; for (i = 0; i < RX_RING_SIZE; i++) { tp->rx_ring[i].status = 0x00000000; @@ -2578,6 +2584,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)) { @@ -2595,6 +2603,8 @@ dev->interrupt = 1; #endif + tp->nir++; + do { csr5 = inl(ioaddr + CSR5); /* Acknowledge all of the current interrupt sources ASAP. */ @@ -2703,12 +2713,6 @@ tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; outl(tp->csr6 | 0x2002, ioaddr + CSR6); } - if (csr5 & TimerInt) { - if (tulip_debug > 2) - printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n", - dev->name, csr5); - outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); - } if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { if (tp->link_change) (tp->link_change)(dev, csr5); @@ -2716,6 +2720,13 @@ /* Clear all error sources, included undocumented ones! */ outl(0x0800f7ba, ioaddr + CSR5); } + if (csr5 & TimerInt) { + if (tulip_debug > 2) + 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 (--work_budget < 0) { if (tulip_debug > 1) printk(KERN_WARNING "%s: Too much work during an interrupt, " @@ -2723,12 +2734,43 @@ /* Acknowledge all interrupt sources. */ outl(0x8001ffff, ioaddr + CSR5); /* Clear all interrupting sources, set timer to re-enable. */ - outl(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, + outl(((~csr5) & 0x0001ebef) | NormalIntr | 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 in suspend mode: try to get an skb; if received packets pending: receive */ + if (tp->susp_rx || (tp->rx_skbuff[entry] != NULL && ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned)))) { + if (tp->susp_rx) + printk(KERN_WARNING "%s: in rx suspend mode: (%lu) (cur_rx = %u, ttimer = %d) try to get some skbs\n", dev->name, tp->nir, tp->cur_rx, tp->ttimer); + tulip_rx(dev); + tp->susp_rx = 0; + entry = tp->cur_rx % RX_RING_SIZE; + } + + /* check if we card is in suspend mode */ + if (tp->rx_skbuff[entry] == NULL) { + printk(KERN_WARNING "%s: in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d) go/stay in suspend mode\n", dev->name, tp->nir, tp->cur_rx, tp->ttimer); + tp->susp_rx = 1; + if (tp->ttimer == 0 || (inl(ioaddr + CSR11) & 0xffff) == 0) { + printk(KERN_WARNING "%s: in rx suspend mode: (%lu) set timer\n", dev->name, tp->nir); + 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", - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |