// $Header$ // Kernel Version: // VERSION = 2 // PATCHLEVEL = 4 // SUBLEVEL = 1 // EXTRAVERSION = diff -ur 2.4/drivers/net/tulip/interrupt.c build-2.4/drivers/net/tulip/interrupt.c --- 2.4/drivers/net/tulip/interrupt.c Sun Feb 11 00:38:34 2001 +++ build-2.4/drivers/net/tulip/interrupt.c Mon Feb 12 16:44:19 2001 @@ -23,7 +23,7 @@ -static int tulip_refill_rx(struct net_device *dev) +int tulip_refill_rx(struct net_device *dev) { struct tulip_private *tp = (struct tulip_private *)dev->priv; int entry; @@ -332,10 +332,17 @@ /* Josip Loncaric at ICASE did extensive experimentation to develop a good interrupt mitigation setting.*/ outl(0x8b240000, ioaddr + CSR11); - } else { + } else if (tp->chip_id == LC82C168) { + /* the LC82C168 doesn't have a hw timer.*/ + outl(0x00, ioaddr + CSR7); + tp->ttimer = 1; + mod_timer(&tp->timer, RUN_AT(HZ/50)); + } else { /* Mask all interrupting sources, set timer to re-enable. */ outl(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7); + printk(KERN_ERR "interrupts got masked, new csr7 is %d.\n", + ((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt); outl(0x0012, ioaddr + CSR11); } break; @@ -353,16 +360,24 @@ /* check if the card is in suspend mode */ entry = tp->dirty_rx % RX_RING_SIZE; if (tp->rx_buffers[entry].skb == NULL) { - if (tulip_debug > 1) - printk(KERN_WARNING "%s: in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d, rx = %d) go/stay in suspend mode\n", dev->name, tp->nir, tp->cur_rx, tp->ttimer, rx); - if (tp->ttimer == 0 || (inl(ioaddr + CSR11) & 0xffff) == 0) { - if (tulip_debug > 1) - 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); + if (tulip_debug > 1) { + printk(KERN_WARNING "%s: in rx suspend mode: (%lu) (tp->cur_rx = %u, ttimer = %d, rx = %d) go/stay in suspend mode\n", + dev->name, tp->nir, tp->cur_rx, tp->ttimer, rx); + } + if (tp->chip_id == LC82C168) { + outl(0x00, ioaddr + CSR7); tp->ttimer = 1; + mod_timer(&tp->timer, RUN_AT(HZ/50)); + } else { + if (tp->ttimer == 0 || (inl(ioaddr + CSR11) & 0xffff) == 0) { + if (tulip_debug > 1) + 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; + } } } diff -ur 2.4/drivers/net/tulip/media.c build-2.4/drivers/net/tulip/media.c --- 2.4/drivers/net/tulip/media.c Sun Feb 11 00:38:34 2001 +++ build-2.4/drivers/net/tulip/media.c Mon Feb 12 16:53:25 2001 @@ -419,3 +419,59 @@ return 0; } +/* Modified version of tulip_check_duplex: + * Always update the 100mbps bit, even if the + * full duplex bit didn't change. + * Manfred Spraul + */ +int pnic_check_duplex(struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + int mii_reg1, mii_reg5, negotiated, duplex; + int new_csr6; + + mii_reg1 = tulip_mdio_read(dev, tp->phys[0], 1); + mii_reg5 = tulip_mdio_read(dev, tp->phys[0], 5); + if (tulip_debug > 1) + printk(KERN_INFO "%s: MII status %4.4x, Link partner report " + "%4.4x.\n", dev->name, mii_reg1, mii_reg5); + if (mii_reg1 == 0xffff) + return -2; + if ((mii_reg1 & 0x0004) == 0) { + int new_reg1 = tulip_mdio_read(dev, tp->phys[0], 1); + if ((new_reg1 & 0x0004) == 0) { + if (tulip_debug > 1) + printk(KERN_INFO "%s: No link beat on the MII interface," + " status %4.4x.\n", dev->name, new_reg1); + return -1; + } + } + negotiated = mii_reg5 & tp->advertising[0]; + /* 100baseTx-FD or 10T-FD, but not 100-HD */ + duplex = ((negotiated & 0x0300) == 0x0100 + || (negotiated & 0x00C0) == 0x0040) || + tp->full_duplex_lock; + + new_csr6 = tp->csr6; + if (negotiated & 0x038) /* 100mbps. */ + new_csr6 &= ~0x00400000; + else + new_csr6 |= 0x00400000; + if (duplex) + new_csr6 |= 0x0200; + else + new_csr6 &= ~0x0200; + if (new_csr6 != tp->csr6) { + tp->full_duplex = duplex; + tp->csr6 = new_csr6; + tulip_restart_rxtx(tp, tp->csr6); + if (tulip_debug > 0) + printk(KERN_INFO "%s: Setting %s-duplex based on MII" + "#%d link partner capability of %4.4x.\n", + dev->name, tp->full_duplex ? "full" : "half", + tp->phys[0], mii_reg5); + return 1; + } + return 0; +} + diff -ur 2.4/drivers/net/tulip/pnic.c build-2.4/drivers/net/tulip/pnic.c --- 2.4/drivers/net/tulip/pnic.c Sun Feb 11 00:38:34 2001 +++ build-2.4/drivers/net/tulip/pnic.c Mon Feb 12 16:44:59 2001 @@ -62,6 +62,11 @@ dev->name, phy_reg, csr5); if (inl(ioaddr + CSR5) & TPLnkFail) { outl((inl(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7); + /* If we use an external MII, then we mustn't use the + * internal negotiation. + */ + if (tulip_media_cap[dev->if_port] & MediaIsMII) + return; if (! tp->nwayset || jiffies - dev->trans_start > 1*HZ) { tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff); tulip_outl_csr(tp, tp->csr6, CSR6); @@ -70,11 +75,18 @@ dev->trans_start = jiffies; } } else if (inl(ioaddr + CSR5) & TPLnkPass) { - pnic_do_nway(dev); + if (tulip_media_cap[dev->if_port] & MediaIsMII) { + spin_lock(&tp->lock); + pnic_check_duplex(dev); + spin_unlock(&tp->lock); + } else { + pnic_do_nway(dev); + } outl((inl(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7); } } +int tulip_refill_rx(struct net_device *dev); void pnic_timer(unsigned long data) { @@ -82,10 +94,19 @@ struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; int next_tick = 60*HZ; - + + if(tp->ttimer != 0) { + disable_irq(dev->irq); + tulip_refill_rx(dev); + enable_irq(dev->irq); + outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); + tp->ttimer = 0; + } if (tulip_media_cap[dev->if_port] & MediaIsMII) { - if (tulip_check_duplex(dev) > 0) + spin_lock_irq(&tp->lock); + if (pnic_check_duplex(dev) > 0) next_tick = 3*HZ; + spin_unlock_irq(&tp->lock); } else { int csr12 = inl(ioaddr + CSR12); int new_csr6 = tp->csr6 & ~0x40C40200;